#primary_key(klass) (private)
[ GitHub ]# File 'activerecord/lib/active_record/associations/belongs_to_association.rb', line 161
def primary_key(klass) reflection.association_primary_key(klass) end
123456789_123456789_123456789_123456789_123456789_
| Relationships & Source Files | |
| Extension / Inclusion / Inheritance Descendants | |
|
Subclasses:
|
|
| Super Chains via Extension / Inclusion / Inheritance | |
|
Class Chain:
self,
SingularAssociation,
Association
|
|
|
Instance Chain:
self,
SingularAssociation,
Association
|
|
| Inherits: |
ActiveRecord::Associations::SingularAssociation
|
| Defined in: | activerecord/lib/active_record/associations/belongs_to_association.rb |
Association - Inherited| #collection? | Whether the association represents a single record or a collection of records. |
| #disable_joins, | |
| #loaded? | Has the \target been already \loaded? |
| #options, #owner, #reflection, | |
| #stale_target? | The target is stale if the target no longer points to the record(s) that the relevant foreign_key(s) refers to. |
| #target, | |
| #target= | Sets the target of this association to \target, and the \loaded flag to |
| #violates_strict_loading?, #find_target?, | |
| #foreign_key_present? | Returns true if there is a foreign key present on the owner which references the target. |
SingularAssociation - Inherited| #build, | |
| #force_reload_reader | Implements the reload reader method, e.g. |
| #reader | Implements the reader method, e.g. |
| #reset | Resets the \loaded flag to |
| #writer | Implements the writer method, e.g. |
| #_create_record, #find_target, #replace, #scope_for_create, #set_new_record | |
Association - Inherited| #async_load_target, #create, #create!, #extensions, #initialize_attributes, #inversed_from, #inversed_from_queries, | |
| #klass | Returns the class of the target. |
| #load_target | Loads the \target if needed and returns it. |
| #loaded! | Asserts the \target has been loaded setting the \loaded flag to |
| #marshal_dump | We can't dump @reflection and @through_reflection since it contains the scope proc. |
| #marshal_load, | |
| #reload | Reloads the \target and returns |
| #remove_inverse_instance | Remove the inverse association, if possible. |
| #reset | Resets the \loaded flag to |
| #reset_negative_cache, #reset_scope, #scope, | |
| #set_inverse_instance | Set the inverse association, if possible. |
| #set_inverse_instance_from_queries, #set_strict_loading, #active_record_primary_key_values, #association_primary_key_values, | |
| #association_scope | The scope for this association. |
| #build_record, #enqueue_destroy_association, | |
| #ensure_klass_exists! | Reader and writer methods call this so that consistent errors are presented when the association target class does not exist. |
| #find_target, | |
| #foreign_key_for? | Returns true if record contains the foreign_key. |
| #foreign_key_values, #inversable?, #inverse_association_for, | |
| #inverse_reflection_for | Can be redefined by subclasses, notably polymorphic belongs_to The record parameter is necessary to support polymorphic inverses as we must check for the association in the specific class of the record. |
| #invertible_for? | Returns true if inverse association on the given record needs to be set. |
| #matches_foreign_key?, #owner_foreign_key_matches_record?, | |
| #raise_on_type_mismatch! | Raises |
| #record_foreign_key_matches_owner?, #scope_for_create, | |
| #skip_statement_cache? | Returns true if statement cache should be skipped on the association reader. |
| #skip_strict_loading, | |
| #stale_state | This should be implemented to return the values of the relevant key(s) on the owner, so that when stale_state is different from the value stored on the last find_target, the target is stale. |
| #target_scope | Can be overridden (i.e. in |
BelongsToAssociation
# File 'activerecord/lib/active_record/associations/belongs_to_association.rb', line 9
def initialize(owner, reflection) super aliases = owner.class.attribute_aliases fk = reflection.foreign_key resolved_fk = fk.is_a?(Array) ? fk.map { |k| aliases[k] || k } : (aliases[fk] || fk) @foreign_key = ActiveRecord::Key.for(resolved_fk) if reflection.polymorphic? ft = reflection.foreign_type @foreign_type = aliases[ft] || ft end end
Boolean (readonly, private)
# File 'activerecord/lib/active_record/associations/belongs_to_association.rb', line 135
def find_target? !loaded? && foreign_key_present? && klass end
# File 'activerecord/lib/active_record/associations/belongs_to_association.rb', line 7
attr_reader :foreign_key, :foreign_type
Boolean (readonly, private)
# File 'activerecord/lib/active_record/associations/belongs_to_association.rb', line 165
def foreign_key_present? foreign_key.all? { |fk| owner.read_attribute(fk) } end
# File 'activerecord/lib/active_record/associations/belongs_to_association.rb', line 7
attr_reader :foreign_key, :foreign_type
Boolean (readonly, private)
# File 'activerecord/lib/active_record/associations/belongs_to_association.rb', line 139
def require_counter_update? reflection.counter_cache_column && owner.persisted? end
Boolean (readonly)
# File 'activerecord/lib/active_record/associations/belongs_to_association.rb', line 100
def saved_change_to_target? foreign_key.any? { |fk| owner.saved_change_to_attribute?(fk) } end
Boolean (readonly)
# File 'activerecord/lib/active_record/associations/belongs_to_association.rb', line 92
def target_changed? foreign_key.any? { |fk| owner.attribute_changed?(fk) } || (!foreign_key_present? && target&.new_record?) end
Boolean (readonly)
# File 'activerecord/lib/active_record/associations/belongs_to_association.rb', line 96
def target_previously_changed? foreign_key.any? { |fk| owner.attribute_previously_changed?(fk) } end
Boolean (readonly)
# File 'activerecord/lib/active_record/associations/belongs_to_association.rb', line 64
def updated? @updated end
# File 'activerecord/lib/active_record/associations/belongs_to_association.rb', line 68
def decrement_counters update_counters(-1) end
# File 'activerecord/lib/active_record/associations/belongs_to_association.rb', line 76
def decrement_counters_before_last_save if reflection.polymorphic? model_type_was = owner.attribute_before_last_save(foreign_type) model_was = owner.class.polymorphic_class_for(model_type_was) if model_type_was else model_was = klass end values = foreign_key.map { |fk| owner.attribute_before_last_save(fk) } foreign_key_was = foreign_key.composite? ? (values if values.all?) : values.first if foreign_key_was && model_was < ActiveRecord::Base update_counters_via_scope(model_was, foreign_key_was, -1) end end
# File 'activerecord/lib/active_record/associations/belongs_to_association.rb', line 55
def default(&block) writer(owner.instance_exec(&block)) if reader.nil? end
# File 'activerecord/lib/active_record/associations/belongs_to_association.rb', line 21
def handle_dependency return unless load_target case [:dependent] when :destroy raise ActiveRecord::Rollback unless target.destroy when :destroy_async primary_key_column = reflection.active_record_primary_key ids = foreign_key.map { |col| owner.public_send(col) } association_class = if reflection.polymorphic? owner.public_send(foreign_type) else reflection.klass end enqueue_destroy_association( owner_model_name: owner.class.to_s, owner_id: owner.id, association_class: association_class.to_s, association_ids: foreign_key.composite? ? [ids] : ids, association_primary_key_column: primary_key_column, ensuring_owner_was_method: .fetch(:ensuring_owner_was, nil) ) else target.public_send([:dependent]) end end
# File 'activerecord/lib/active_record/associations/belongs_to_association.rb', line 72
def increment_counters update_counters(1) end
# File 'activerecord/lib/active_record/associations/belongs_to_association.rb', line 50
def inversed_from(record) replace_keys(record) super end
Boolean (private)
# File 'activerecord/lib/active_record/associations/belongs_to_association.rb', line 169
def invertible_for?(record) inverse = inverse_reflection_for(record) inverse && (inverse.has_one? || inverse.klass.has_many_inversing) end
# File 'activerecord/lib/active_record/associations/belongs_to_association.rb', line 161
def primary_key(klass) reflection.association_primary_key(klass) end
# File 'activerecord/lib/active_record/associations/belongs_to_association.rb', line 105
def replace(record) if record raise_on_type_mismatch!(record) set_inverse_instance(record) @updated = true elsif target remove_inverse_instance(target) end replace_keys(record, force: true) self.target = record end
# File 'activerecord/lib/active_record/associations/belongs_to_association.rb', line 143
def replace_keys(record, force: false) target_key_values = record ? ActiveRecord::Key.for(primary_key(record.class)).map { |col| record.read_attribute(col) } : [] owner_key_values = foreign_key.map { |fk| owner.read_attribute(fk) } return if !force && owner_key_values == target_key_values owner_pk = ActiveRecord::Key.for(owner.class.primary_key) # Preserve shared primary key columns only if another foreign key # column can be cleared to disassociate the record. preserve_owner_pk = record.nil? && foreign_key.any? { |key| !owner_pk.include?(key) } foreign_key.each_with_index do |key, index| next if preserve_owner_pk && owner_pk.include?(key) owner.write_attribute(key, target_key_values[index]) end end
# File 'activerecord/lib/active_record/associations/belongs_to_association.rb', line 59
def reset super @updated = false end
# File 'activerecord/lib/active_record/associations/belongs_to_association.rb', line 174
def stale_state values = foreign_key.map do |fk| owner.read_attribute(fk) { |n| owner.send(:missing_attribute, n, caller) } end foreign_key.composite? ? (values if values.any?) : values.first end
# File 'activerecord/lib/active_record/associations/belongs_to_association.rb', line 119
def update_counters(by) if require_counter_update? && foreign_key_present? if target && !stale_target? target.increment!(reflection.counter_cache_column, by, touch: reflection.[:touch]) else update_counters_via_scope(klass, foreign_key.value_of(owner), by) end end end
# File 'activerecord/lib/active_record/associations/belongs_to_association.rb', line 129
def update_counters_via_scope(klass, values, by) primary_key = ActiveRecord::Key.for(primary_key(klass)) scope = klass.all_queries_scope.where!(primary_key.where_hash(values)) scope.update_counters(reflection.counter_cache_column => by, touch: reflection.[:touch]) end