class ActiveRecord::Associations::AssociationProxy

:nodoc:
instantiation of the actual post records.
is computed directly through SQL and does not trigger by itself the
blog.posts.count
The @target object is not loaded until needed. For example,
ActiveRecord::Associations::HasManyAssociation.
though the object behind blog.posts is not an Array, but an
blog.posts.class # => Array
corner case, it even removes the class method and that’s why you get
unknown methods to @target via method_missing. As a
This class has most of the basic instance methods removed, and delegates
the @reflection object represents a :has_many macro.
@owner, the collection of its posts as @target, and
the association proxy in blog.posts has the object in blog as
blog = Blog.find(:first)
end
has_many :posts
class Blog < ActiveRecord::Base
For example, given
ActiveRecord::Reflection::AssociationReflection.
about is available in @reflection. That’s an instance of the class
object, known as the @target. The kind of association any proxy is
holds the association, known as the @owner, and the actual associated
Association proxies in Active Record are middlemen between the object that
HasOneThroughAssociation
HasManyThroughAssociation
HasManyAssociation
HasAndBelongsToManyAssociation
AssociationCollection
BelongsToPolymorphicAssociation
HasOneAssociation
BelongsToAssociation
AssociationProxy
This is the root class of all association proxies:

def ===(other)

removal above doesn't catch it. Loads the \target if needed.
Forwards === explicitly to the \target because the instance method
def ===(other)
  load_target
  other === @target
end

def aliased_table_name


post.comments.aliased_table_name # => "comments"

Returns the name of the table of the related class:
def aliased_table_name
  @reflection.klass.table_name
end

def conditions

option of the macro, if given, or +nil+ otherwise.
Returns the SQL string that corresponds to the :conditions
def conditions
  @conditions ||= interpolate_sql(@reflection.sanitized_conditions) if @reflection.sanitized_conditions
end

def dependent?

Does the association have a :dependent option?
def dependent?
  @reflection.options[:dependent]
end

def flatten_deeper(array)

deeper solves the majority of the problems.
Array#flatten has problems with recursive arrays. Going one level
def flatten_deeper(array)
  array.collect { |element| (element.respond_to?(:flatten) && !element.is_a?(Hash)) ? element.flatten : element }.flatten
end

def foreign_key_present

this scenario (both vanilla and polymorphic).
still being a new record). Currently, only +belongs_to+ presents
available for an association without having the object itself (and
Can be overwritten by associations that might have the foreign key
def foreign_key_present
  false
end

def initialize(owner, reflection)

def initialize(owner, reflection)
  @owner, @reflection = owner, reflection
  reflection.check_validity!
  Array(reflection.options[:extend]).each { |ext| proxy_extend(ext) }
  reset
end

def inspect

Forwards the call to the target. Loads the \target if needed.
def inspect
  load_target
  @target.inspect
end

def interpolate_sql(sql, record = nil)

def interpolate_sql(sql, record = nil)
  @owner.send(:interpolate_sql, sql, record)
end

def load_target

not reraised. The proxy is \reset and +nil+ is the return value.
ActiveRecord::RecordNotFound is rescued within the method, and it is

+load_target+ unconditionally to get the \target.
If the \target is already \loaded it is just returned. Thus, you can call

which is expected to be provided by descendants.
This method is abstract in the sense that it relies on +find_target+,

Loads the \target if needed and returns it.
def load_target
  return nil unless defined?(@loaded)
  if !loaded? and (!@owner.new_record? || foreign_key_present)
    @target = find_target
  end
  @loaded = true
  @target
rescue ActiveRecord::RecordNotFound
  reset
end

def loaded

Asserts the \target has been loaded setting the \loaded flag to +true+.
def loaded
  @loaded = true
end

def loaded?

Has the \target been already \loaded?
def loaded?
  @loaded
end

def merge_options_from_reflection!(options)

Merges into +options+ the ones coming from the reflection.
def merge_options_from_reflection!(options)
  options.reverse_merge!(
    :group   => @reflection.options[:group],
    :having  => @reflection.options[:having],
    :limit   => @reflection.options[:limit],
    :offset  => @reflection.options[:offset],
    :joins   => @reflection.options[:joins],
    :include => @reflection.options[:include],
    :select  => @reflection.options[:select],
    :readonly  => @reflection.options[:readonly]
  )
end

def method_missing(method, *args, &block)

Forwards any missing method call to the \target.
def method_missing(method, *args, &block)
  if load_target
    if @target.respond_to?(method)
      @target.send(method, *args, &block)
    else
      super
    end
  end
end

def owner_quoted_id

Returns the ID of the owner, quoted if needed.
def owner_quoted_id
  @owner.quoted_id
end

def proxy_owner

Returns the owner of the proxy.
def proxy_owner
  @owner
end

def proxy_reflection

by the proxy.
Returns the reflection object that represents the association handled
def proxy_reflection
  @reflection
end

def proxy_target

Returns the \target of the proxy, same as +target+.
def proxy_target
  @target
end

def quoted_record_ids(records)


quoted_record_ids(records) # => "23,56,58,67"

if needed. The result is ready to be inserted into a SQL IN clause.
Returns a string with the IDs of +records+ joined with a comma, quoted
def quoted_record_ids(records)
  records.map { |record| record.quoted_id }.join(',')
end

def raise_on_type_mismatch(record)

a sanity check when you are about to assign an associated record.
the kind of the class of the associated objects. Meant to be used as
Raises ActiveRecord::AssociationTypeMismatch unless +record+ is of
def raise_on_type_mismatch(record)
  unless record.is_a?(@reflection.klass) || record.is_a?(@reflection.class_name.constantize)
    message = "#{@reflection.class_name}(##{@reflection.klass.object_id}) expected, got #{record.class}(##{record.class.object_id})"
    raise ActiveRecord::AssociationTypeMismatch, message
  end
end

def reload

Reloads the \target and returns +self+ on success.
def reload
  reset
  load_target
  self unless @target.nil?
end

def reset

Resets the \loaded flag to +false+ and sets the \target to +nil+.
def reset
  @loaded = false
  @target = nil
end

def respond_to?(*args)

Does the proxy or its \target respond to +symbol+?
def respond_to?(*args)
  proxy_respond_to?(*args) || (load_target && @target.respond_to?(*args))
end

def sanitize_sql(sql, table_name = @reflection.klass.quoted_table_name)

Forwards the call to the reflection class.
def sanitize_sql(sql, table_name = @reflection.klass.quoted_table_name)
  @reflection.klass.send(:sanitize_sql, sql, table_name)
end

def send(method, *args)

def send(method, *args)
  if proxy_respond_to?(method)
    super
  else
    load_target
    @target.send(method, *args)
  end
end

def set_belongs_to_association_for(record)

If the association is polymorphic the type of the owner is also set.
Assigns the ID of the owner to the corresponding foreign key in +record+.
def set_belongs_to_association_for(record)
  if @reflection.options[:as]
    record["#{@reflection.options[:as]}_id"]   = @owner.id unless @owner.new_record?
    record["#{@reflection.options[:as]}_type"] = @owner.class.base_class.name.to_s
  else
    unless @owner.new_record?
      primary_key = @reflection.options[:primary_key] || :id
      record[@reflection.primary_key_name] = @owner.send(primary_key)
    end
  end
end

def set_inverse_instance(record, instance)

def set_inverse_instance(record, instance)
  return if record.nil? || !we_can_set_the_inverse_on_this?(record)
  inverse_relationship = @reflection.inverse_of
  unless inverse_relationship.nil?
    record.send(:"set_#{inverse_relationship.name}_target", instance)
  end
end

def target

Returns the target of this proxy, same as +proxy_target+.
def target
  @target
end

def target=(target)

Sets the target of this proxy to \target, and the \loaded flag to +true+.
def target=(target)
  @target = target
  loaded
end

def we_can_set_the_inverse_on_this?(record)

Override in subclasses
def we_can_set_the_inverse_on_this?(record)
  false
end

def with_scope(*args, &block)

Forwards +with_scope+ to the reflection.
def with_scope(*args, &block)
  @reflection.klass.send :with_scope, *args, &block
end