123456789_123456789_123456789_123456789_123456789_

Class: ActiveRecord::Reflection::AbstractReflection

Do not use. This class is for internal use only.

Overview

Class Method Summary

Instance Attribute Summary

Instance Method Summary

Constructor Details

.newAbstractReflection

[ GitHub ]

  
# File 'activerecord/lib/active_record/reflection.rb', line 158

def initialize
  @class_name = nil
  @counter_cache_column = nil
  @inverse_of = nil
  @inverse_which_updates_counter_cache_defined = false
  @inverse_which_updates_counter_cache = nil
end

Instance Attribute Details

#counter_must_be_updated_by_has_many?Boolean (readonly)

[ GitHub ]

  
# File 'activerecord/lib/active_record/reflection.rb', line 318

def counter_must_be_updated_by_has_many?
  !inverse_updates_counter_in_memory? && has_cached_counter?
end

#has_active_cached_counter?Boolean (readonly)

Returns whether this association has a counter cache and its column values were backfilled (and so it is used internally by methods like size/any?/etc).

[ GitHub ]

  
# File 'activerecord/lib/active_record/reflection.rb', line 309

def has_active_cached_counter?
  return false unless has_cached_counter?

  counter_cache = options[:counter_cache] ||
                  (inverse_which_updates_counter_cache && inverse_which_updates_counter_cache.options[:counter_cache])

  counter_cache[:active] != false
end

#has_cached_counter?Boolean (readonly)

Returns whether this association has a counter cache.

The counter_cache option must be given on either the owner or inverse association, and the column must be present on the owner.

[ GitHub ]

  
# File 'activerecord/lib/active_record/reflection.rb', line 301

def has_cached_counter?
  options[:counter_cache] ||
    inverse_which_updates_counter_cache && inverse_which_updates_counter_cache.options[:counter_cache] &&
    active_record.has_attribute?(counter_cache_column)
end

#inverse_updates_counter_cache? (readonly)

[ GitHub ]

  
# File 'activerecord/lib/active_record/reflection.rb', line 291

alias inverse_updates_counter_cache? inverse_which_updates_counter_cache

#inverse_updates_counter_in_memory?Boolean (readonly)

[ GitHub ]

  
# File 'activerecord/lib/active_record/reflection.rb', line 293

def inverse_updates_counter_in_memory?
  inverse_of && inverse_which_updates_counter_cache == inverse_of
end

#strict_loading?Boolean (readonly)

[ GitHub ]

  
# File 'activerecord/lib/active_record/reflection.rb', line 338

def strict_loading?
  options[:strict_loading]
end

#through_reflection?Boolean (readonly)

[ GitHub ]

  
# File 'activerecord/lib/active_record/reflection.rb', line 166

def through_reflection?
  false
end

Instance Method Details

#actual_source_reflection (protected)

FIXME: this is a horrible name

[ GitHub ]

  
# File 'activerecord/lib/active_record/reflection.rb', line 349

def actual_source_reflection # FIXME: this is a horrible name
  self
end

#alias_candidate(name)

[ GitHub ]

  
# File 'activerecord/lib/active_record/reflection.rb', line 322

def alias_candidate(name)
  "#{plural_name}_#{name}"
end

#build_association(attributes, &block)

Returns a new, unsaved instance of the associated class. attributes will be passed to the class’s constructor.

[ GitHub ]

  
# File 'activerecord/lib/active_record/reflection.rb', line 176

def build_association(attributes, &block)
  klass.new(attributes, &block)
end

#build_scope(table, predicate_builder = predicate_builder(table), klass = self.klass)

[ GitHub ]

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

def build_scope(table, predicate_builder = predicate_builder(table), klass = self.klass)
  Relation.create(
    klass,
    table: table,
    predicate_builder: predicate_builder
  )
end

#chain

[ GitHub ]

  
# File 'activerecord/lib/active_record/reflection.rb', line 326

def chain
  collect_join_chain
end

#check_validity_of_inverse!

[ GitHub ]

  
# File 'activerecord/lib/active_record/reflection.rb', line 258

def check_validity_of_inverse!
  if !polymorphic? && has_inverse?
    if inverse_of.nil?
      raise InverseOfAssociationNotFoundError.new(self)
    end
    if inverse_of == self
      raise InverseOfAssociationRecursiveError.new(self)
    end
  end
end

#class_name

Returns the class name for the macro.

composed_of :balance, class_name: 'Money' returns 'Money' has_many :clients returns 'Client'

[ GitHub ]

  
# File 'activerecord/lib/active_record/reflection.rb', line 184

def class_name
  @class_name ||= -(options[:class_name] || derive_class_name).to_s
end

#constraints

[ GitHub ]

  
# File 'activerecord/lib/active_record/reflection.rb', line 234

def constraints
  chain.flat_map(&:scopes)
end

#counter_cache_column

[ GitHub ]

  
# File 'activerecord/lib/active_record/reflection.rb', line 238

def counter_cache_column
  @counter_cache_column ||= begin
    counter_cache = options[:counter_cache]

    if belongs_to?
      if counter_cache
        counter_cache[:column] || -"#{active_record.name.demodulize.underscore.pluralize}_count"
      end
    else
      -((counter_cache && -counter_cache[:column]) || "#{name}_count")
    end
  end
end

#ensure_option_not_given_as_class!(option_name) (private)

[ GitHub ]

  
# File 'activerecord/lib/active_record/reflection.rb', line 362

def ensure_option_not_given_as_class!(option_name)
  if options[option_name] && options[option_name].class == Class
    raise ArgumentError, "A class was passed to `:#{option_name}` but we are expecting a string."
  end
end

#inverse_of

[ GitHub ]

  
# File 'activerecord/lib/active_record/reflection.rb', line 252

def inverse_of
  return unless inverse_name

  @inverse_of ||= klass._reflect_on_association inverse_name
end

#inverse_which_updates_counter_cache Also known as: #inverse_updates_counter_cache?

We need to avoid the following situation:

* An associated record is deleted via record.destroy
* Hence the callbacks run, and they find a belongs_to on the record with a
  :counter_cache options which points back at our owner. So they update the
  counter cache.
* In which case, we must make sure to *not* update the counter cache, or else
  it will be decremented twice.

Hence this method.

[ GitHub ]

  
# File 'activerecord/lib/active_record/reflection.rb', line 279

def inverse_which_updates_counter_cache
  unless @inverse_which_updates_counter_cache_defined
    if counter_cache_column
      inverse_candidates = inverse_of ? [inverse_of] : klass.reflect_on_all_associations(:belongs_to)
      @inverse_which_updates_counter_cache = inverse_candidates.find do |inverse|
        inverse.counter_cache_column == counter_cache_column && (inverse.polymorphic? || inverse.klass == active_record)
      end
    end
    @inverse_which_updates_counter_cache_defined = true
  end
  @inverse_which_updates_counter_cache
end

#join_scope(table, foreign_table, foreign_klass)

[ GitHub ]

  
# File 'activerecord/lib/active_record/reflection.rb', line 194

def join_scope(table, foreign_table, foreign_klass)
  predicate_builder = predicate_builder(table)
  scope_chain_items = join_scopes(table, predicate_builder)
  klass_scope       = klass_join_scope(table, predicate_builder)

  if type
    klass_scope.where!(type => foreign_klass.polymorphic_name)
  end

  scope_chain_items.inject(klass_scope, &:merge!)

  primary_key_column_names = Array(join_primary_key)
  foreign_key_column_names = Array(join_foreign_key)

  primary_foreign_key_pairs = primary_key_column_names.zip(foreign_key_column_names)

  primary_foreign_key_pairs.each do |primary_key_column_name, foreign_key_column_name|
    klass_scope.where!(table[primary_key_column_name].eq(foreign_table[foreign_key_column_name]))
  end

  if klass.finder_needs_type_condition?
    klass_scope.where!(klass.send(:type_condition, table))
  end

  klass_scope
end

#join_scopes(table, predicate_builder, klass = self.klass, record = nil)

[ GitHub ]

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

def join_scopes(table, predicate_builder, klass = self.klass, record = nil) # :nodoc:
  if scope
    [scope_for(build_scope(table, predicate_builder, klass), record)]
  else
    []
  end
end

#klass_join_scope(table, predicate_builder)

[ GitHub ]

  
# File 'activerecord/lib/active_record/reflection.rb', line 229

def klass_join_scope(table, predicate_builder) # :nodoc:
  relation = build_scope(table, predicate_builder)
  klass.scope_for_association(relation)
end

#predicate_builder(table) (private)

[ GitHub ]

  
# File 'activerecord/lib/active_record/reflection.rb', line 354

def predicate_builder(table)
  PredicateBuilder.new(TableMetadata.new(klass, table))
end

#primary_key(klass) (private)

[ GitHub ]

  
# File 'activerecord/lib/active_record/reflection.rb', line 358

def primary_key(klass)
  klass.primary_key || raise(UnknownPrimaryKey.new(klass))
end

#scopes

Returns a list of scopes that should be applied for this ::ActiveRecord::Reflection object when querying the database.

[ GitHub ]

  
# File 'activerecord/lib/active_record/reflection.rb', line 190

def scopes
  scope ? [scope] : []
end

#strict_loading_violation_message(owner)

[ GitHub ]

  
# File 'activerecord/lib/active_record/reflection.rb', line 342

def strict_loading_violation_message(owner)
  message = +"`#{owner}` is marked for strict_loading."
  message << " The #{polymorphic? ? "polymorphic association" : "#{klass} association"}"
  message << " named `:#{name}` cannot be lazily loaded."
end

#table_name

[ GitHub ]

  
# File 'activerecord/lib/active_record/reflection.rb', line 170

def table_name
  klass.table_name
end