123456789_123456789_123456789_123456789_123456789_

Class: ActiveRecord::AssociationRoute

Do not use. This class is for internal use only.
Relationships & Source Files
Namespace Children
Classes:
Inherits: Object
Defined in: activerecord/lib/active_record/association_route.rb

Overview

An association's resolved connection from a concrete origin class to its destination.

Constant Summary

Class Method Summary

Instance Attribute Summary

Instance Method Summary

Constructor Details

.new(link:) ⇒ AssociationRoute

[ GitHub ]

  
# File 'activerecord/lib/active_record/association_route.rb', line 196

def initialize(link:)
  @link = link
  initialize_keys
  @key_pairs = pairs_for(origin_key, destination_key)
  @reference_pairs = if link.constraints.empty?
    @key_pairs
  else
    pairs_for(reference_origin_key, reference_destination_key)
  end
  @hash = [self.class, link].hash
  freeze
end

Instance Attribute Details

#_destination_key (readonly)

Physical (alias-resolved) counterparts of the above.

[ GitHub ]

  
# File 'activerecord/lib/active_record/association_route.rb', line 219

attr_reader :_origin_key, :_destination_key, :_reference_origin_key, :_reference_destination_key

#_origin_key (readonly)

Physical (alias-resolved) counterparts of the above.

[ GitHub ]

  
# File 'activerecord/lib/active_record/association_route.rb', line 219

attr_reader :_origin_key, :_destination_key, :_reference_origin_key, :_reference_destination_key

#_reference_destination_key (readonly)

Physical (alias-resolved) counterparts of the above.

[ GitHub ]

  
# File 'activerecord/lib/active_record/association_route.rb', line 219

attr_reader :_origin_key, :_destination_key, :_reference_origin_key, :_reference_destination_key

#_reference_origin_key (readonly)

Physical (alias-resolved) counterparts of the above.

[ GitHub ]

  
# File 'activerecord/lib/active_record/association_route.rb', line 219

attr_reader :_origin_key, :_destination_key, :_reference_origin_key, :_reference_destination_key

#destination_key (readonly)

[ GitHub ]

  
# File 'activerecord/lib/active_record/association_route.rb', line 216

attr_reader :origin_key, :destination_key, :reference_origin_key, :reference_destination_key

#hash (readonly)

[ GitHub ]

  
# File 'activerecord/lib/active_record/association_route.rb', line 214

attr_reader :hash

#origin_key (readonly)

[ GitHub ]

  
# File 'activerecord/lib/active_record/association_route.rb', line 216

attr_reader :origin_key, :destination_key, :reference_origin_key, :reference_destination_key

#predicate_accepts_bare_id? ⇒ Boolean (readonly)

[ GitHub ]

  
# File 'activerecord/lib/active_record/association_route.rb', line 221

def predicate_accepts_bare_id?
  !origin_key.composite? && !reference_origin_key.composite?
end

#reference_destination_key (readonly)

[ GitHub ]

  
# File 'activerecord/lib/active_record/association_route.rb', line 216

attr_reader :origin_key, :destination_key, :reference_origin_key, :reference_destination_key

#reference_origin_key (readonly)

[ GitHub ]

  
# File 'activerecord/lib/active_record/association_route.rb', line 216

attr_reader :origin_key, :destination_key, :reference_origin_key, :reference_destination_key

Instance Method Details

#==(other) Also known as: #eql?

[ GitHub ]

  
# File 'activerecord/lib/active_record/association_route.rb', line 209

def ==(other)
  other.class == self.class && link == other.link
end

#build_match_normalizers(origin_class, destination_class) (private)

[ GitHub ]

  
# File 'activerecord/lib/active_record/association_route.rb', line 307

def build_match_normalizers(origin_class, destination_class)
  origin_normalizers = destination_normalizers = nil
  each_match.with_index do |(origin_column, destination_column), index|
    origin_type = origin_class.type_for_attribute(origin_column)
    destination_type = destination_class.type_for_attribute(destination_column)
    origin_normalizer, destination_normalizer = normalizers_for_types(origin_type, destination_type)

    if origin_normalizer
      (origin_normalizers ||= Array.new(@key_pairs.length))[index] = origin_normalizer
    end
    if destination_normalizer
      (destination_normalizers ||= Array.new(@key_pairs.length))[index] = destination_normalizer
    end
  end
  [origin_normalizers&.freeze, destination_normalizers&.freeze].freeze
end

#clear_reference(reference_record)

[ GitHub ]

  
# File 'activerecord/lib/active_record/association_route.rb', line 290

def clear_reference(reference_record, **)
  @link.clear_reference(reference_record, **)
end

#destination_fixed_values

[ GitHub ]

  
# File 'activerecord/lib/active_record/association_route.rb', line 282

def destination_fixed_values
  EMPTY_FIXED_VALUES
end

#each_constraint(&block)

[ GitHub ]

  
# File 'activerecord/lib/active_record/association_route.rb', line 274

def each_constraint(&block)
  @constraint_pairs.each(&block)
end

#each_match(&block)

[ GitHub ]

  
# File 'activerecord/lib/active_record/association_route.rb', line 225

def each_match(&block)
  @key_pairs.each(&block)
end

#each_matching_origin(origins, destination)

[ GitHub ]

  
# File 'activerecord/lib/active_record/association_route.rb', line 246

def each_matching_origin(origins, destination)
  return enum_for(__method__, origins, destination) unless block_given?

  # The destination's conversion depends on the owner's attribute types, so
  # cache its converted value separately for each owner class.
  comparisons_by_class = {}
  origins.each do |origin|
    origin_normalizers, destination_value = comparisons_by_class[origin.class] ||= begin
      origin_normalizers, destination_normalizers = match_normalizers(origin_class: origin.class, destination_class: destination.class)
      [origin_normalizers, destination_key.value_of(destination, destination_normalizers)]
    end

    yield origin if origin_key.value_of(origin, origin_normalizers) == destination_value
  end
end

#each_reference(&block)

[ GitHub ]

  
# File 'activerecord/lib/active_record/association_route.rb', line 270

def each_reference(&block)
  @reference_pairs.each(&block)
end

#eql?(other)

Alias for #==.

[ GitHub ]

  
# File 'activerecord/lib/active_record/association_route.rb', line 212

alias_method :eql?, :==

#initialize_keys (private)

[ GitHub ]

  
# File 'activerecord/lib/active_record/association_route.rb', line 295

def initialize_keys
  @origin_key = link.match&.reference_key
  @destination_key = link.match&.target_key
  @reference_origin_key = link.reference_key
  @reference_destination_key = link.reference&.target_key
  @_origin_key = link._match_reference_key
  @_destination_key = link._match_target_key
  @_reference_origin_key = link._reference_key
  @_reference_destination_key = link._target_key
  @constraint_pairs = link.constraints.empty? ? EMPTY_KEY_PAIRS : pairs_for(link.constraints.reference_key, link.constraints.target_key)
end

#key_values_match?(origin, destination) ⇒ Boolean

[ GitHub ]

  
# File 'activerecord/lib/active_record/association_route.rb', line 241

def key_values_match?(origin, destination)
  origin_normalizers, destination_normalizers = match_normalizers(origin_class: origin.class, destination_class: destination.class)
  _origin_key._value_of(origin, origin_normalizers) == _destination_key._value_of(destination, destination_normalizers)
end

#match_normalizers(origin_class:, destination_class:)

Per-column conversions for comparing origin and destination key values. A nil list or entry leaves the corresponding values unchanged.

[ GitHub ]

  
# File 'activerecord/lib/active_record/association_route.rb', line 231

def match_normalizers(origin_class:, destination_class:)
  # Schema contexts are replaced on reload, so key by them to avoid
  # reusing conversions computed from outdated attribute types.
  cache = Cache.for(self)
  by_destination = cache.fetch_or_store(origin_class.schema_context) { Cache.new }
  by_destination.fetch_or_store(destination_class.schema_context) do
    build_match_normalizers(origin_class, destination_class)
  end
end

#normalizers_for_types(origin_type, destination_type) (private)

[ GitHub ]

  
# File 'activerecord/lib/active_record/association_route.rb', line 324

def normalizers_for_types(origin_type, destination_type)
  unless origin_type.type == destination_type.type
    [STRING_NORMALIZER, STRING_NORMALIZER]
  end
end

#origin_fixed_values

[ GitHub ]

  
# File 'activerecord/lib/active_record/association_route.rb', line 278

def origin_fixed_values
  @link.fixed_values
end

#origin_reference_complete?(origin) ⇒ Boolean

[ GitHub ]

  
# File 'activerecord/lib/active_record/association_route.rb', line 262

def origin_reference_complete?(origin)
  _reference_origin_key.all? { |column| !origin._read_attr(column).nil? }
end

#pairs_for(origin_key, destination_key) (private)

[ GitHub ]

  
# File 'activerecord/lib/active_record/association_route.rb', line 330

def pairs_for(origin_key, destination_key)
  origin_key.zip(destination_key).map!(&:freeze).freeze if origin_key && destination_key
end

#reference_needs_update?(origin, destination) ⇒ Boolean

[ GitHub ]

  
# File 'activerecord/lib/active_record/association_route.rb', line 266

def reference_needs_update?(origin, destination)
  @link.reference_needs_update?(origin, destination)
end

#write(origin, destination, force: true)

[ GitHub ]

  
# File 'activerecord/lib/active_record/association_route.rb', line 286

def write(origin, destination, force: true)
  @link.write_reference(origin, destination, force: force)
end