Module: Mongoid::History::Tracker

Extended by:
ActiveSupport::Concern
Defined in:
lib/mongoid/history/tracker.rb

Instance Method Summary collapse

Instance Method Details

#affectedHashWithIndifferentAccess

Deprecated.

Similar to #tracked_changes, but contains only a single value for each affected field:

- :create and :update return the modified values
- :destroy returns original values

Included for legacy compatibility.

Returns:

  • (HashWithIndifferentAccess)

    a change set in the format: { field_1: value, field_2: value }



148
149
150
151
152
153
154
# File 'lib/mongoid/history/tracker.rb', line 148

def affected
  target = action.to_sym == :destroy ? :from : :to
  @affected ||= tracked_changes.inject(HashWithIndifferentAccess.new) do |h, (k, v)|
    h[k] = v[target]
    h
  end
end

#redo!(modifier = nil) ⇒ Object



41
42
43
44
45
46
47
48
49
50
51
# File 'lib/mongoid/history/tracker.rb', line 41

def redo!(modifier = nil)
  if action.to_sym == :destroy
    re_destroy
  elsif action.to_sym == :create
    re_create
  elsif Mongoid::Compatibility::Version.mongoid3?
    trackable.update_attributes!(redo_attr(modifier), without_protection: true)
  else
    trackable.update_attributes!(redo_attr(modifier))
  end
end

#redo_attr(modifier) ⇒ Object



64
65
66
67
68
69
70
# File 'lib/mongoid/history/tracker.rb', line 64

def redo_attr(modifier)
  redo_hash = affected.easy_unmerge(original)
  redo_hash.easy_merge!(modified)
  modifier_field = trackable.history_trackable_options[:modifier_field]
  redo_hash[modifier_field] = modifier if modifier_field
  localize_keys(redo_hash)
end

#trackableObject



76
77
78
# File 'lib/mongoid/history/tracker.rb', line 76

def trackable
  @trackable ||= trackable_parents_and_trackable.last
end

#trackable_parentObject



84
85
86
# File 'lib/mongoid/history/tracker.rb', line 84

def trackable_parent
  @trackable_parent ||= trackable_parents_and_trackable[-2]
end

#trackable_parent_classClass

Returns the class of the trackable, irrespective of whether the trackable object has been destroyed.

Returns:

  • (Class)

    the class of the trackable



160
161
162
# File 'lib/mongoid/history/tracker.rb', line 160

def trackable_parent_class
  association_chain.first['name'].constantize
end

#trackable_parentsObject



80
81
82
# File 'lib/mongoid/history/tracker.rb', line 80

def trackable_parents
  @trackable_parents ||= trackable_parents_and_trackable[0, -1]
end

#trackable_rootObject



72
73
74
# File 'lib/mongoid/history/tracker.rb', line 72

def trackable_root
  @trackable_root ||= trackable_parents_and_trackable.first
end

#tracked_changesHashWithIndifferentAccess

Outputs a :from, :to hash for each affected field. Intentionally excludes fields which are not tracked, even if there are tracked values for such fields present in the database.

Returns:

  • (HashWithIndifferentAccess)

    a change set in the format: { field_1: new_val, field_2: old_val, to: new_val }



94
95
96
97
98
99
# File 'lib/mongoid/history/tracker.rb', line 94

def tracked_changes
  @tracked_changes ||= (modified.keys | original.keys).inject(HashWithIndifferentAccess.new) do |h, k|
    h[k] = { from: original[k], to: modified[k] }.delete_if { |_, vv| vv.nil? }
    h
  end.delete_if { |k, v| v.blank? || !trackable_parent_class.tracked?(k) }
end

#tracked_editsHashWithIndifferentAccess

Outputs summary of edit actions performed: :add, :modify, :remove, or :array. Does deep comparison of arrays. Useful for creating human-readable representations of the history tracker. Considers changing a value to ‘blank’ to be a removal.

Returns:

  • (HashWithIndifferentAccess)

    a change set in the format: { add: { field_1: new_val, … },

    modify: { field_2: {from: old_val, to: new_val}, ... },
    remove: { field_3: old_val },
    array: { field_4: {add: ['foo', 'bar'], remove: ['baz']} } }
    


110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
# File 'lib/mongoid/history/tracker.rb', line 110

def tracked_edits
  return @tracked_edits if @tracked_edits
  @tracked_edits = HashWithIndifferentAccess.new

  tracked_changes.each do |k, v|
    next if v[:from].blank? && v[:to].blank?

    if trackable_parent_class.tracked_embeds_many?(k)
      prepare_tracked_edits_for_embeds_many(k, v)
    elsif v[:from].blank?
      @tracked_edits[:add] ||= {}
      @tracked_edits[:add][k] = v[:to]
    elsif v[:to].blank?
      @tracked_edits[:remove] ||= {}
      @tracked_edits[:remove][k] = v[:from]
    elsif v[:from].is_a?(Array) && v[:to].is_a?(Array)
      @tracked_edits[:array] ||= {}
      old_values = v[:from] - v[:to]
      new_values = v[:to] - v[:from]
      @tracked_edits[:array][k] = { add: new_values, remove: old_values }.delete_if { |_, vv| vv.blank? }
    else
      @tracked_edits[:modify] ||= {}
      @tracked_edits[:modify][k] = v
    end
  end
  @tracked_edits
end

#undo!(modifier = nil) ⇒ Object



29
30
31
32
33
34
35
36
37
38
39
# File 'lib/mongoid/history/tracker.rb', line 29

def undo!(modifier = nil)
  if action.to_sym == :destroy
    re_create
  elsif action.to_sym == :create
    re_destroy
  elsif Mongoid::Compatibility::Version.mongoid3?
    trackable.update_attributes!(undo_attr(modifier), without_protection: true)
  else
    trackable.update_attributes!(undo_attr(modifier))
  end
end

#undo_attr(modifier) ⇒ Object



53
54
55
56
57
58
59
60
61
62
# File 'lib/mongoid/history/tracker.rb', line 53

def undo_attr(modifier)
  undo_hash = affected.easy_unmerge(modified)
  undo_hash.easy_merge!(original)
  modifier_field = trackable.history_trackable_options[:modifier_field]
  undo_hash[modifier_field] = modifier if modifier_field
  (modified.keys - undo_hash.keys).each do |k|
    undo_hash[k] = nil
  end
  localize_keys(undo_hash)
end