module PaperTrailAssociationTracking::RecordTrail
Public Instance Methods
Utility method for reifying. Anything executed inside the block will appear like a new record.
> .. as best as I can tell, the purpose of > appear_as_new_record
was to attempt to prevent the callbacks in > AutosaveAssociation (which is the module responsible for persisting > foreign key changes earlier than most people want most of the time > because backwards compatibility or the maintainer hates himself or > something) from running. By also stubbing out persisted? we can > actually prevent those. A more stable option might be to use suppress > instead, similar to the other branch in reify_has_one. > -Sean Griffin (github.com/paper-trail-gem/paper_trail/pull/899)
@api private
# File lib/paper_trail_association_tracking/record_trail.rb, line 19 def appear_as_new_record @record.instance_eval { alias :old_new_record? :new_record? alias :new_record? :present? alias :old_persisted? :persisted? alias :persisted? :nil? } yield @record.instance_eval { alias :new_record? :old_new_record? alias :persisted? :old_persisted? } end
@api private
# File lib/paper_trail_association_tracking/record_trail.rb, line 43 def data_for_create data = super add_transaction_id_to(data) data end
@api private
# File lib/paper_trail_association_tracking/record_trail.rb, line 60 def data_for_destroy data = super add_transaction_id_to(data) data end
Used during `record_update`, returns a hash of data suitable for an AR `create`. That is, all the attributes of the nascent `Version` record.
@api private
# File lib/paper_trail_association_tracking/record_trail.rb, line 88 def data_for_update(*args) data = super add_transaction_id_to(data) data end
Returns data for record_update_columns
@api private
# File lib/paper_trail_association_tracking/record_trail.rb, line 106 def data_for_update_columns(*args) data = super add_transaction_id_to(data) data end
@api private
# File lib/paper_trail_association_tracking/record_trail.rb, line 34 def record_create version = super if version update_transaction_id(version) save_associations(version) end end
@api private
# File lib/paper_trail_association_tracking/record_trail.rb, line 50 def record_destroy(*args) version = super if version && version.respond_to?(:errors) && version.errors.empty? update_transaction_id(version) save_associations(version) end version end
Returns a boolean indicating whether to store serialized version diffs in the `object_changes` column of the version record. @api private
# File lib/paper_trail_association_tracking/record_trail.rb, line 69 def record_object_changes? @record.paper_trail_options[:save_changes] && @record.class.paper_trail.version_class.column_names.include?("object_changes") end
@api private
# File lib/paper_trail_association_tracking/record_trail.rb, line 75 def record_update(**opts) version = super if version && version.respond_to?(:errors) && version.errors.empty? update_transaction_id(version) save_associations(version) end version end
@api private
# File lib/paper_trail_association_tracking/record_trail.rb, line 95 def record_update_columns(*args) version = super if version && version.respond_to?(:errors) && version.errors.empty? update_transaction_id(version) save_associations(version) end version end
Saves associations if the join table for `VersionAssociation` exists.
# File lib/paper_trail_association_tracking/record_trail.rb, line 113 def save_associations(version) return unless ::PaperTrail.config.track_associations? save_bt_associations(version) save_habtm_associations(version) end
Save all `belongs_to` associations. @api private
# File lib/paper_trail_association_tracking/record_trail.rb, line 121 def save_bt_associations(version) @record.class.reflect_on_all_associations(:belongs_to).each do |assoc| save_bt_association(assoc, version) end end
When a record is created, updated, or destroyed, we determine what the HABTM associations looked like before any changes were made, by using the `paper_trail_habtm` data structure. Then, we create `VersionAssociation` records for each of the associated records. @api private
# File lib/paper_trail_association_tracking/record_trail.rb, line 132 def save_habtm_associations(version) @record.class.reflect_on_all_associations(:has_and_belongs_to_many).each do |a| next unless save_habtm_association?(a) habtm_assoc_ids(a).each do |id| ::PaperTrail::VersionAssociation.create( version_id: version.transaction_id, foreign_key_name: a.name, foreign_key_id: id, foreign_type: a.klass ) end end end
Private Instance Methods
# File lib/paper_trail_association_tracking/record_trail.rb, line 148 def add_transaction_id_to(data) return unless @record.class.paper_trail.version_class.column_names.include?("transaction_id") data[:transaction_id] = ::PaperTrail.request.transaction_id end
Given a HABTM association, returns an array of ids.
@api private
# File lib/paper_trail_association_tracking/record_trail.rb, line 156 def habtm_assoc_ids(habtm_assoc) current = @record.send(habtm_assoc.name).to_a.map(&:id) # TODO: `pluck` would use less memory removed = @record.paper_trail_habtm.try(:[], habtm_assoc.name).try(:[], :removed) || [] added = @record.paper_trail_habtm.try(:[], habtm_assoc.name).try(:[], :added) || [] current + removed - added end
Save a single `belongs_to` association. @api private
# File lib/paper_trail_association_tracking/record_trail.rb, line 165 def save_bt_association(assoc, version) assoc_version_args = { version_id: version.id, foreign_key_name: assoc.foreign_key } if assoc.options[:polymorphic] foreign_type = @record.send(assoc.foreign_type) if foreign_type && ::PaperTrail.request.enabled_for_model?(foreign_type.constantize) assoc_version_args[:foreign_key_id] = @record.send(assoc.foreign_key) assoc_version_args[:foreign_type] = foreign_type end elsif ::PaperTrail.request.enabled_for_model?(assoc.klass) assoc_version_args[:foreign_key_id] = @record.send(assoc.foreign_key) assoc_version_args[:foreign_type] = assoc.klass end if assoc_version_args.key?(:foreign_key_id) ::PaperTrail::VersionAssociation.create(assoc_version_args) end end
Returns true if the given HABTM association should be saved. @api private
# File lib/paper_trail_association_tracking/record_trail.rb, line 189 def save_habtm_association?(assoc) @record.class.paper_trail_save_join_tables.include?(assoc.name) || ::PaperTrail.request.enabled_for_model?(assoc.klass) end
# File lib/paper_trail_association_tracking/record_trail.rb, line 194 def update_transaction_id(version) return unless @record.class.paper_trail.version_class.column_names.include?("transaction_id") if ::PaperTrail.transaction? && ::PaperTrail.request.transaction_id.nil? ::PaperTrail.request.transaction_id = version.id version.transaction_id = version.id version.save end end