Class: Mongoid::Tracking::Tracker
- Inherits:
-
Object
- Object
- Mongoid::Tracking::Tracker
- Includes:
- Readers
- Defined in:
- lib/mongoid/tracking/tracker.rb
Overview
This internal class handles all interaction for a track field.
Instance Method Summary collapse
-
#add(how_much = 1, date = Time.now) ⇒ Object
Update methods.
- #dec(date = Time.now) ⇒ Object
- #erase(date = Time.now) ⇒ Object
- #inc(date = Time.now) ⇒ Object
-
#initialize(owner, field, aggregate_data) ⇒ Tracker
constructor
A new instance of Tracker.
-
#method_missing(name, *args, &block) ⇒ Object
Delegate all missing methods to the aggregate accessors.
- #reset(how_much, date = Time.now) ⇒ Object
- #set(how_much, date = Time.now) ⇒ Object
Methods included from Readers
#all_values, #date_cleanup, #first_date, #first_value, #last_date, #last_days, #last_value, #on, #today, #yesterday
Constructor Details
#initialize(owner, field, aggregate_data) ⇒ Tracker
Returns a new instance of Tracker.
9 10 11 12 13 14 15 16 17 18 19 20 |
# File 'lib/mongoid/tracking/tracker.rb', line 9 def initialize(owner, field, aggregate_data) @owner, @for = owner, field @for_data = @owner.internal_track_name(@for) @data = @owner.read_attribute(@for_data) if @data.nil? @owner.write_attribute(@for_data, {}) @data = @owner.read_attribute(@for_data) end @aggregate_data = aggregate_data.first if aggregate_data.first end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(name, *args, &block) ⇒ Object
Delegate all missing methods to the aggregate accessors. This enables us to call an aggregation token after the tracking field.
Example:
<tt>@object.visits.browsers ...</tt>
29 30 31 32 |
# File 'lib/mongoid/tracking/tracker.rb', line 29 def method_missing(name, *args, &block) super unless @owner.aggregate_fields.member?(name) @owner.send("#{name}_with_track".to_sym, @for, *args, &block) end |
Instance Method Details
#add(how_much = 1, date = Time.now) ⇒ Object
Update methods
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
# File 'lib/mongoid/tracking/tracker.rb', line 35 def add(how_much = 1, date = Time.now) raise Errors::ModelNotSaved, "Can't update a new record. Save first!" if @owner.new_record? return if how_much == 0 # Note that the following #update_data method updates our local data # and the current value might differ from the actual value on the # database. Basically, what we do is update our own copy as a cache # but send the command to atomically update the database: we don't # read the actual value in return so that we save round trip delays. # update_data(data_for(date) + how_much, date) @owner.inc(store_key(date), how_much.abs) return unless @owner.aggregated? @owner.aggregate_fields.each do |k, v| next unless token = v.call(@aggregate_data) fk = @owner.class.name.to_s.foreign_key.to_sym selector = { fk => @owner.id, ns: k, key: token.to_s } docs = @owner.aggregate_klass.collection.find(selector) docs.upsert("$inc" => update_hash(how_much.abs, date)) end end |
#dec(date = Time.now) ⇒ Object
64 65 66 |
# File 'lib/mongoid/tracking/tracker.rb', line 64 def dec(date = Time.now) add(-1, date) end |
#erase(date = Time.now) ⇒ Object
103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 |
# File 'lib/mongoid/tracking/tracker.rb', line 103 def erase(date = Time.now) raise Errors::ModelNotSaved, "Can't update a new record" if @owner.new_record? remove_data(date) @owner.unset(store_key(date)) return unless @owner.aggregated? # Need to iterate over all aggregates and send an update or delete # operations over all mongo records @owner.aggregate_fields.each do |(k,v)| fk = @owner.class.name.to_s.foreign_key.to_sym selector = { fk => @owner.id, ns: k } docs = @owner.aggregate_klass.collection.find(selector) docs.update_all("$unset" => update_hash(1, date)) end end |
#inc(date = Time.now) ⇒ Object
60 61 62 |
# File 'lib/mongoid/tracking/tracker.rb', line 60 def inc(date = Time.now) add(1, date) end |
#reset(how_much, date = Time.now) ⇒ Object
86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 |
# File 'lib/mongoid/tracking/tracker.rb', line 86 def reset(how_much, date = Time.now) return erase(date) if how_much.nil? # First, we use the default "set" for the tracking field # This will also update one aggregate but... oh well... set(how_much, date) # Need to iterate over all aggregates and send an update or delete # operations over all mongo records for this aggregate field @owner.aggregate_fields.each do |(k,v)| fk = @owner.class.name.to_s.foreign_key.to_sym selector = { fk => @owner.id, ns: k } docs = @owner.aggregate_klass.collection.find(selector) docs.update_all("$set" => update_hash(how_much.abs, date)) end end |
#set(how_much, date = Time.now) ⇒ Object
68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 |
# File 'lib/mongoid/tracking/tracker.rb', line 68 def set(how_much, date = Time.now) raise Errors::ModelNotSaved, "Can't update a new record" if @owner.new_record? update_data(how_much, date) @owner.set(store_key(date), how_much) return unless @owner.aggregated? @owner.aggregate_fields.each do |(k,v)| next unless token = v.call(@aggregate_data) fk = @owner.class.name.to_s.foreign_key.to_sym selector = { fk => @owner.id, ns: k, key: token.to_s } docs = @owner.aggregate_klass.collection.find(selector) docs.upsert("$set" => update_hash(how_much.abs, date)) end end |