module ActiveRecord::TrackDirtyAssociations::ClassMethods

Public Instance Methods

track_dirty_associations(*association_types) click to toggle source
# File lib/activerecord/track_dirty_associations.rb, line 9
def track_dirty_associations *association_types
  klass = self

  klass.send :after_save, -> { dirty_assocs = {} }

  klass.singleton_class.send :alias_method, :old_has_many, :has_many

  klass.singleton_class.send :define_method, :has_many do |*args, **opts|
    association_type = args.first
    options = opts
    if association_types.empty? || association_types.include?(association_type)
      create_association_methods association_type
      options.merge!({
        after_add: ->(object, association) { add_association association_type, object, association },
        before_remove: ->(object, association) { remove_association association_type, object, association }
      })
    end
    old_has_many *args, options
  end

  klass.singleton_class.send :alias_method, :old_has_one, :has_one

  klass.singleton_class.send :define_method, :has_one do |*args, **opts|
    association_type = args.first
    options = opts
    if association_types.empty? || association_types.include?(association_type)
      create_association_methods association_type
    end
    old_has_one *args, options
  end

  klass.singleton_class.send :alias_method, :old_belongs_to, :belongs_to

  klass.singleton_class.send :define_method, :belongs_to do |*args, **opts|
    association_type = args.first
    options = opts
    if association_types.empty? || association_types.include?(association_type)
      create_association_methods association_type
    end
    old_belongs_to *args, options
  end

  klass.singleton_class.send :define_method, :belongs_to do |*args, **opts|
    association_type = args.first
    options = opts
    if association_types.empty? || association_types.include?(association_type)
      create_association_methods association_type
    end
    old_belongs_to *args, options
  end

  define_method 'dirty_associations' do
    dirty_associations = dirty_assocs || {}
    association_types.each do |association_type|
      dirty_associations[association_type] = association_changes(association_type) if association_changes(association_type).any?
    end
    dirty_associations
  end

  define_method 'dirty_associations?' do
    send(:dirty_associations).any?
  end
end

Private Instance Methods

add_association(association_type, object, association) click to toggle source
# File lib/activerecord/track_dirty_associations.rb, line 85
def add_association association_type, object, association
  handle_association :added, association_type, object, association
end
create_association_methods(association_type) click to toggle source
# File lib/activerecord/track_dirty_associations.rb, line 75
def create_association_methods association_type
  define_method "#{association_type}_changes" do
    association_changes(association_type)
  end

  define_method "#{association_type}_changed?" do
    send("#{association_type}_changes".to_sym).any?
  end
end
handle_association(action, association_type, object, association) click to toggle source
# File lib/activerecord/track_dirty_associations.rb, line 93
def handle_association action, association_type, object, association
  return if object.new_record?
  object.dirty_assocs = {} unless object.dirty_assocs
  object.dirty_assocs[association_type] = {} unless object.dirty_assocs[association_type]
  (object.dirty_assocs[association_type][action] ||= []) << association
end
remove_association(association_type, object, association) click to toggle source
# File lib/activerecord/track_dirty_associations.rb, line 89
def remove_association association_type, object, association
  handle_association :removed, association_type, object, association
end