module Mongoid::History::Trackable::MyInstanceMethods
Public Instance Methods
_create_relation(name, value)
click to toggle source
# File lib/mongoid/history/trackable.rb, line 136 def _create_relation(name, value) send("create_#{self.class.relation_alias(name)}!", value) end
_get_relation(name)
click to toggle source
# File lib/mongoid/history/trackable.rb, line 132 def _get_relation(name) send(self.class.relation_alias(name)) end
history_tracks()
click to toggle source
# File lib/mongoid/history/trackable.rb, line 85 def history_tracks @history_tracks ||= self.class.tracker_class.where( scope: related_scope, association_chain: association_hash ).asc(:version) end
redo!(modifier = nil, options_or_version = nil)
click to toggle source
# File lib/mongoid/history/trackable.rb, line 117 def redo!(modifier = nil, options_or_version = nil) versions = get_versions_criteria(options_or_version).to_a versions.sort! { |v1, v2| v1.version <=> v2.version } versions.each do |v| redo_attr = v.redo_attr(modifier) if Mongoid::Compatibility::Version.mongoid3? assign_attributes(redo_attr, without_protection: true) save! else update_attributes!(redo_attr) end end end
undo(modifier = nil, options_or_version = nil)
click to toggle source
undo :from => 1, :to => 5 undo 4 undo :last => 10
# File lib/mongoid/history/trackable.rb, line 95 def undo(modifier = nil, options_or_version = nil) versions = get_versions_criteria(options_or_version).to_a versions.sort! { |v1, v2| v2.version <=> v1.version } versions.each do |v| undo_attr = v.undo_attr(modifier) if Mongoid::Compatibility::Version.mongoid3? # update_attributes! not bypassing rails 3 protected attributes assign_attributes(undo_attr, without_protection: true) else # assign_attributes with 'without_protection' option does not work with rails 4/mongoid 4 self.attributes = undo_attr end end end
undo!(modifier = nil, options_or_version = nil)
click to toggle source
undo! :from => 1, :to => 5 undo! 4 undo! :last => 10
# File lib/mongoid/history/trackable.rb, line 112 def undo!(modifier = nil, options_or_version = nil) undo(modifier, options_or_version) save! end
Protected Instance Methods
increment_current_version?(action)
click to toggle source
# File lib/mongoid/history/trackable.rb, line 328 def increment_current_version?(action) action != :destroy && !ancestor_flagged_for_destroy?(_parent) end
track_history_for_action(action) { || ... }
click to toggle source
# File lib/mongoid/history/trackable.rb, line 332 def track_history_for_action(action) if track_history_for_action?(action) current_version = increment_current_version?(action) ? increment_current_version : next_version last_track = self.class.tracker_class.create!( history_tracker_attributes(action.to_sym) .merge(version: current_version, action: action.to_s, trackable: self) ) end clear_trackable_memoization begin yield rescue => e if track_history_for_action?(action) send("#{history_trackable_options[:version_field]}=", current_version - 1) last_track.destroy end raise e end end
track_history_for_action?(action)
click to toggle source
# File lib/mongoid/history/trackable.rb, line 324 def track_history_for_action?(action) track_history? && !(action.to_sym == :update && modified_attributes_for_update.blank?) end
Private Instance Methods
ancestor_flagged_for_destroy?(doc)
click to toggle source
# File lib/mongoid/history/trackable.rb, line 142 def ancestor_flagged_for_destroy?(doc) doc && (doc.flagged_for_destroy? || ancestor_flagged_for_destroy?(doc._parent)) end
association_hash(node = self)
click to toggle source
# File lib/mongoid/history/trackable.rb, line 193 def association_hash(node = self) # We prefer to look up associations through the parent record because # we're assured, through the object creation, it'll exist. Whereas we're not guaranteed # the child to parent (embedded_in, belongs_to) relation will be defined if node._parent meta = node._parent.relations.values.find do |relation| if Mongoid::Compatibility::Version.mongoid3? relation.class_name == node.metadata.class_name.to_s && relation.name == node.metadata.name elsif Mongoid::Compatibility::Version.mongoid6_or_older? relation.class_name == node.relation_metadata.class_name.to_s && relation.name == node.relation_metadata.name elsif Mongoid::Compatibility::Version.mongoid7_or_newer? relation.class_name == node._association.class_name.to_s && relation.name == node._association.name end end end # if root node has no meta, and should use class name instead name = meta ? meta.key.to_s : node.class.name ActiveSupport::OrderedHash['name', name, 'id', node.id] end
clear_trackable_memoization()
click to toggle source
# File lib/mongoid/history/trackable.rb, line 273 def clear_trackable_memoization @history_tracker_attributes = @modified_attributes_for_create = @modified_attributes_for_update = @history_tracks = nil end
expand_nested_document_key_value(document_key, value)
click to toggle source
Handle nested document tracking of changes
@example
expand_nested_document_key('embedded.document.changed_field', 'old']) #=> { 'embedded' => {'document' => { 'changed_field' => 'old' }}}
@param [String] document_key key with dots @param [?] value
@return [Hash<String, ?>]
# File lib/mongoid/history/trackable.rb, line 306 def expand_nested_document_key_value(document_key, value) expanded_key = value document_key.to_s.split('.').reverse.each do |key| expanded_key = { key => expanded_key } end expanded_key end
get_versions_criteria(options_or_version)
click to toggle source
# File lib/mongoid/history/trackable.rb, line 146 def get_versions_criteria(options_or_version) if options_or_version.is_a? Hash options = options_or_version if options[:from] && options[:to] lower = options[:from] >= options[:to] ? options[:to] : options[:from] upper = options[:from] < options[:to] ? options[:to] : options[:from] versions = history_tracks.where(:version.in => (lower..upper).to_a) elsif options[:last] versions = history_tracks.limit(options[:last]) else raise 'Invalid options, please specify (:from / :to) keys or :last key.' end else options_or_version = options_or_version.to_a if options_or_version.is_a?(Range) version_field_name = history_trackable_options[:version_field] version = options_or_version || attributes[version_field_name] || attributes[version_field_name.to_s] version = [version].flatten versions = history_tracks.where(:version.in => version) end versions.desc(:version) end
history_tracker_attributes(action)
click to toggle source
# File lib/mongoid/history/trackable.rb, line 244 def history_tracker_attributes(action) return @history_tracker_attributes if @history_tracker_attributes modifier_field = history_trackable_options[:modifier_field] @history_tracker_attributes = { association_chain: traverse_association_chain, scope: related_scope } @history_tracker_attributes[:modifier] = send(modifier_field) if modifier_field original, modified = transform_changes(modified_attributes_for_action(action)) @history_tracker_attributes[:original] = original @history_tracker_attributes[:modified] = modified @history_tracker_attributes end
increment_current_version()
click to toggle source
# File lib/mongoid/history/trackable.rb, line 318 def increment_current_version next_version.tap { |version| send("#{history_trackable_options[:version_field]}=", version) } end
modified_attributes_for_action(action)
click to toggle source
Returns a Hash of field name to pairs of original and modified values for each tracked field for a given action.
@param [ String | Symbol ] action The modification action (:create, :update, :destroy)
@return [ Hash<String, Array<Object>> ] the pairs of original and modified
values for each field
# File lib/mongoid/history/trackable.rb, line 224 def modified_attributes_for_action(action) case action.to_sym when :destroy then modified_attributes_for_destroy when :create then modified_attributes_for_create else modified_attributes_for_update end end
modified_attributes_for_create()
click to toggle source
# File lib/mongoid/history/trackable.rb, line 236 def modified_attributes_for_create @modified_attributes_for_create ||= Mongoid::History::Attributes::Create.new(self).attributes end
modified_attributes_for_destroy()
click to toggle source
# File lib/mongoid/history/trackable.rb, line 240 def modified_attributes_for_destroy @modified_attributes_for_destroy ||= Mongoid::History::Attributes::Destroy.new(self).attributes end
modified_attributes_for_update()
click to toggle source
# File lib/mongoid/history/trackable.rb, line 232 def modified_attributes_for_update @modified_attributes_for_update ||= Mongoid::History::Attributes::Update.new(self).attributes end
next_version()
click to toggle source
# File lib/mongoid/history/trackable.rb, line 314 def next_version (send(history_trackable_options[:version_field]) || 0) + 1 end
track_create(&block)
click to toggle source
# File lib/mongoid/history/trackable.rb, line 261 def track_create(&block) track_history_for_action(:create, &block) end
track_destroy(&block)
click to toggle source
# File lib/mongoid/history/trackable.rb, line 269 def track_destroy(&block) track_history_for_action(:destroy, &block) unless destroyed? end
track_update(&block)
click to toggle source
# File lib/mongoid/history/trackable.rb, line 265 def track_update(&block) track_history_for_action(:update, &block) end
transform_changes(changes)
click to toggle source
Transform hash of pair of changes into an `original` and `modified` hash Nested document keys (key name with dots) are expanded
@param [Hash<Array>] changes
@return [Array<Hash<?>,Hash<?>>] <description>
# File lib/mongoid/history/trackable.rb, line 283 def transform_changes(changes) original = {} modified = {} changes.each_pair do |k, modification_pair| o, m = modification_pair original.deep_merge!(expand_nested_document_key_value(k, o)) unless o.nil? modified.deep_merge!(expand_nested_document_key_value(k, m)) unless m.nil? end [original, modified] end
traverse_association_chain(node = self)
click to toggle source
# File lib/mongoid/history/trackable.rb, line 189 def traverse_association_chain(node = self) (node._parent ? traverse_association_chain(node._parent) : []).tap { |list| list << association_hash(node) } end