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
-
VALID_OPTIONS =
# File 'activerecord/lib/active_record/associations/builder/association.rb', line 24[ :anonymous_class, :primary_key, :foreign_key, :dependent, :validate, :inverse_of, :strict_loading, :query_constraints, :deprecated ].freeze
Class Attribute Summary
- .extensions rw
Class Method Summary
- .build(model, name, scope, options, &block)
- .create_reflection(model, name, scope, options, &block)
- .add_after_commit_jobs_callback(model, dependent) private
- .add_destroy_callbacks(model, reflection) private
- .build_scope(scope) private
- .check_dependent_options(dependent, model) private
-
.define_accessors(model, reflection, mixin)
private
Defines the setter and getter methods for the association class Post <
::ActiveRecord::Base - .define_callbacks(model, reflection) private
- .define_change_tracking_methods(model, reflection, mixin) private
- .define_extensions(model, name) private
- .define_validations(model, reflection) private
- .macro private
- .valid_dependent_options private
- .valid_options(options) private
- .validate_options(options) private
Class Attribute Details
.extensions (rw)
[ GitHub ]# File 'activerecord/lib/active_record/associations/builder/association.rb', line 20
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 164
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 151
def self.add_destroy_callbacks(model, reflection) if reflection.deprecated? # If :dependent is set, destroying the record has a side effect that # would no longer happen if the association is removed. model.before_destroy do report_deprecated_association(reflection, context: ":dependent has a side effect here") end end 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 28
def self.build(model, name, scope, , &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, , &block) ActiveSupport::CodeGenerator.batch(model.generated_association_methods, __FILE__, __LINE__) do |mixin| define_accessors(model, reflection, mixin) define_change_tracking_methods(model, reflection, mixin) end define_callbacks(model, reflection) define_validations(model, reflection) reflection end
.build_scope(scope) (private)
[ GitHub ]# File 'activerecord/lib/active_record/associations/builder/association.rb', line 58
def self.build_scope(scope) if scope && scope.arity == 0 scope_body = ActiveSupport::Ractors.try_shareable_proc(scope) proc { instance_exec(&scope_body) } else scope end end
.check_dependent_options(dependent, model) (private)
[ GitHub ]# File 'activerecord/lib/active_record/associations/builder/association.rb', line 141
def self.(dependent, model) if dependent == :destroy_async && !model.destroy_association_async_job = "A valid destroy_association_async_job is required to use `dependent: :destroy_async` on associations" raise ActiveRecord::ConfigurationError, end unless .include?(dependent) raise ArgumentError, "The :dependent option must be one of #{}, but is :#{dependent}" end end
.create_reflection(model, name, scope, options, &block)
# File 'activerecord/lib/active_record/associations/builder/association.rb', line 45
def self.create_reflection(model, name, scope, , &block) raise ArgumentError, "association names must be a Symbol" unless name.kind_of?(Symbol) () extension = define_extensions(model, name, &block) [:extend] = [*[:extend], extension] if extension scope = build_scope(scope) ActiveRecord::Reflection.create(macro, name, scope, , model) end
.define_accessors(model, reflection, mixin) (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...
# File 'activerecord/lib/active_record/associations/builder/association.rb', line 105
def self.define_accessors(model, reflection, mixin) name = reflection.name mixin.define_cached_method(name, namespace: :association_reader) do |batch| batch << <<~RUBY def #{name} association = association(:#{name}) deprecated_associations_api_guard(association, :#{name}) association.reader end RUBY end mixin.define_cached_method(:"#{name}=", namespace: :association_writer) do |batch| batch << <<~RUBY def #{name}=(value) association = association(:#{name}) deprecated_associations_api_guard(association, :#{name}=) association.writer(value) end RUBY end end
.define_callbacks(model, reflection) (private)
[ GitHub ]# File 'activerecord/lib/active_record/associations/builder/association.rb', line 83
def self.define_callbacks(model, reflection) if dependent = reflection.[:dependent] (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, mixin) (private)
[ GitHub ]# File 'activerecord/lib/active_record/associations/builder/association.rb', line 133
def self.define_change_tracking_methods(model, reflection, mixin) # noop end
.define_extensions(model, name) (private)
[ GitHub ]# File 'activerecord/lib/active_record/associations/builder/association.rb', line 79
def self.define_extensions(model, name) # noop end
.define_validations(model, reflection) (private)
[ GitHub ]# File 'activerecord/lib/active_record/associations/builder/association.rb', line 129
def self.define_validations(model, reflection) # noop end
.macro (private)
# File 'activerecord/lib/active_record/associations/builder/association.rb', line 67
def self.macro raise NotImplementedError end
.valid_dependent_options (private)
# File 'activerecord/lib/active_record/associations/builder/association.rb', line 137
def self. raise NotImplementedError end
.valid_options(options) (private)
[ GitHub ]# File 'activerecord/lib/active_record/associations/builder/association.rb', line 71
def self.() VALID_OPTIONS + Association.extensions.flat_map(&:) end
.validate_options(options) (private)
[ GitHub ]# File 'activerecord/lib/active_record/associations/builder/association.rb', line 75
def self.() .assert_valid_keys(()) end