123456789_123456789_123456789_123456789_123456789_

Class: ActiveRecord::Associations::Builder::Association

Do not use. This class is for internal use only.
Relationships & Source Files
Extension / Inclusion / Inheritance Descendants
Subclasses:
Inherits: Object
Defined in: activerecord/lib/active_record/associations/builder/association.rb

Constant Summary

Class Attribute Summary

Class Method Summary

Class Attribute Details

.extensions (rw)

[ GitHub ]

  
# File 'activerecord/lib/active_record/associations/builder/association.rb', line 17

attr_accessor :extensions

Class Method Details

.add_after_commit_jobs_callback(model, dependent) (private)

[ GitHub ]

  
# File 'activerecord/lib/active_record/associations/builder/association.rb', line 145

def self.add_after_commit_jobs_callback(model, dependent)
  if dependent == :destroy_async
    mixin = model.generated_association_methods

    unless mixin.method_defined?(:_after_commit_jobs)
      model.after_commit(-> do
        _after_commit_jobs.each do |job_class, job_arguments|
          job_class.perform_later(**job_arguments)
        end
      end)

      mixin.class_eval <<-CODE, __FILE__, __LINE__ + 1
        def _after_commit_jobs
          @_after_commit_jobs ||= []
        end
      CODE
    end
  end
end

.add_destroy_callbacks(model, reflection) (private)

[ GitHub ]

  
# File 'activerecord/lib/active_record/associations/builder/association.rb', line 140

def self.add_destroy_callbacks(model, reflection)
  name = reflection.name
  model.before_destroy(->(o) { o.association(name).handle_dependency })
end

.build(model, name, scope, options, &block)

[ GitHub ]

  
# File 'activerecord/lib/active_record/associations/builder/association.rb', line 25

def self.build(model, name, scope, options, &block)
  if model.dangerous_attribute_method?(name)
    raise ArgumentError, "You tried to define an association named #{name} on the model #{model.name}, but " \
                         "this will conflict with a method #{name} already defined by Active Record. " \
                         "Please choose a different association name."
  end

  reflection = create_reflection(model, name, scope, options, &block)
  define_accessors(model, reflection)
  define_callbacks(model, reflection)
  define_validations(model, reflection)
  define_change_tracking_methods(model, reflection)
  reflection
end

.build_scope(scope) (private)

[ GitHub ]

  
# File 'activerecord/lib/active_record/associations/builder/association.rb', line 53

def self.build_scope(scope)
  if scope && scope.arity == 0
    proc { instance_exec(&scope) }
  else
    scope
  end
end

.check_dependent_options(dependent, model) (private)

[ GitHub ]

  
# File 'activerecord/lib/active_record/associations/builder/association.rb', line 130

def self.check_dependent_options(dependent, model)
  if dependent == :destroy_async && !model.destroy_association_async_job
    err_message = "A valid destroy_association_async_job is required to use `dependent: :destroy_async` on associations"
    raise ActiveRecord::ConfigurationError, err_message
  end
  unless valid_dependent_options.include?(dependent)
    raise ArgumentError, "The :dependent option must be one of #{valid_dependent_options}, but is :#{dependent}"
  end
end

.create_reflection(model, name, scope, options, &block)

Raises:

  • (ArgumentError)
[ GitHub ]

  
# File 'activerecord/lib/active_record/associations/builder/association.rb', line 40

def self.create_reflection(model, name, scope, options, &block)
  raise ArgumentError, "association names must be a Symbol" unless name.kind_of?(Symbol)

  validate_options(options)

  extension = define_extensions(model, name, &block)
  options[:extend] = [*options[:extend], extension] if extension

  scope = build_scope(scope)

  ActiveRecord::Reflection.create(macro, name, scope, options, model)
end

.define_accessors(model, reflection) (private)

Defines the setter and getter methods for the association class Post < ::ActiveRecord::Base

has_many :comments

end

Post.first.comments and Post.first.comments= methods are defined by this method…

[ GitHub ]

  
# File 'activerecord/lib/active_record/associations/builder/association.rb', line 95

def self.define_accessors(model, reflection)
  mixin = model.generated_association_methods
  name = reflection.name
  define_readers(mixin, name)
  define_writers(mixin, name)
end

.define_callbacks(model, reflection) (private)

[ GitHub ]

  
# File 'activerecord/lib/active_record/associations/builder/association.rb', line 77

def self.define_callbacks(model, reflection)
  if dependent = reflection.options[:dependent]
    check_dependent_options(dependent, model)
    add_destroy_callbacks(model, reflection)
    add_after_commit_jobs_callback(model, dependent)
  end

  Association.extensions.each do |extension|
    extension.build(model, reflection)
  end
end

.define_change_tracking_methods(model, reflection) (private)

[ GitHub ]

  
# File 'activerecord/lib/active_record/associations/builder/association.rb', line 122

def self.define_change_tracking_methods(model, reflection)
  # noop
end

.define_extensions(model, name) (private)

[ GitHub ]

  
# File 'activerecord/lib/active_record/associations/builder/association.rb', line 73

def self.define_extensions(model, name)
  # noop
end

.define_readers(mixin, name) (private)

[ GitHub ]

  
# File 'activerecord/lib/active_record/associations/builder/association.rb', line 102

def self.define_readers(mixin, name)
  mixin.class_eval <<-CODE, __FILE__, __LINE__ + 1
    def #{name}
      association(:#{name}).reader
    end
  CODE
end

.define_validations(model, reflection) (private)

[ GitHub ]

  
# File 'activerecord/lib/active_record/associations/builder/association.rb', line 118

def self.define_validations(model, reflection)
  # noop
end

.define_writers(mixin, name) (private)

[ GitHub ]

  
# File 'activerecord/lib/active_record/associations/builder/association.rb', line 110

def self.define_writers(mixin, name)
  mixin.class_eval <<-CODE, __FILE__, __LINE__ + 1
    def #{name}=(value)
      association(:#{name}).writer(value)
    end
  CODE
end

.macro (private)

Raises:

  • (NotImplementedError)
[ GitHub ]

  
# File 'activerecord/lib/active_record/associations/builder/association.rb', line 61

def self.macro
  raise NotImplementedError
end

.valid_dependent_options (private)

Raises:

  • (NotImplementedError)
[ GitHub ]

  
# File 'activerecord/lib/active_record/associations/builder/association.rb', line 126

def self.valid_dependent_options
  raise NotImplementedError
end

.valid_options(options) (private)

[ GitHub ]

  
# File 'activerecord/lib/active_record/associations/builder/association.rb', line 65

def self.valid_options(options)
  VALID_OPTIONS + Association.extensions.flat_map(&:valid_options)
end

.validate_options(options) (private)

[ GitHub ]

  
# File 'activerecord/lib/active_record/associations/builder/association.rb', line 69

def self.validate_options(options)
  options.assert_valid_keys(valid_options(options))
end