Class: ActiveRecord::Associations::AssociationProxy

Inherits:
Object
  • Object
show all
Defined in:
lib/active_record/associations/association_proxy.rb

Overview

This is the root class of all association proxies:

AssociationProxy
  BelongsToAssociation
    HasOneAssociation
  BelongsToPolymorphicAssociation
  AssociationCollection
    HasAndBelongsToManyAssociation
    HasManyAssociation
      HasManyThroughAssociation
         HasOneThroughAssociation

Association proxies in Active Record are middlemen between the object that holds the association, known as the @owner, and the actual associated object, known as the @target. The kind of association any proxy is about is available in @reflection. That’s an instance of the class ActiveRecord::Reflection::AssociationReflection.

For example, given

class Blog < ActiveRecord::Base
  has_many :posts
end

blog = Blog.find(:first)

the association proxy in blog.posts has the object in blog as @owner, the collection of its posts as @target, and the @reflection object represents a :has_many macro.

This class has most of the basic instance methods removed, and delegates unknown methods to @target via method_missing. As a corner case, it even removes the class method and that’s why you get

blog.posts.class # => Array

though the object behind blog.posts is not an Array, but an ActiveRecord::Associations::HasManyAssociation.

The @target object is not loaded until needed. For example,

blog.posts.count

is computed directly through SQL and does not trigger by itself the instantiation of the actual post records.

Instance Method Summary collapse

Constructor Details

#initialize(owner, reflection) ⇒ AssociationProxy

Returns a new instance of AssociationProxy.



54
55
56
57
58
# File 'lib/active_record/associations/association_proxy.rb', line 54

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

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method, *args) ⇒ Object (private)



168
169
170
171
172
173
174
175
176
# File 'lib/active_record/associations/association_proxy.rb', line 168

def method_missing(method, *args)
  if load_target
    if block_given?
      @target.send(method, *args)  { |*block_args| yield(*block_args) }
    else
      @target.send(method, *args)
    end
  end
end

Instance Method Details

#===(other) ⇒ Object

Explicitly proxy === because the instance method removal above doesn’t catch it.



78
79
80
81
# File 'lib/active_record/associations/association_proxy.rb', line 78

def ===(other)
  load_target
  other === @target
end

#aliased_table_nameObject



83
84
85
# File 'lib/active_record/associations/association_proxy.rb', line 83

def aliased_table_name
  @reflection.klass.table_name
end

#conditionsObject Also known as: sql_conditions



87
88
89
# File 'lib/active_record/associations/association_proxy.rb', line 87

def conditions
  @conditions ||= interpolate_sql(sanitize_sql(@reflection.options[:conditions])) if @reflection.options[:conditions]
end

#inspectObject



120
121
122
123
# File 'lib/active_record/associations/association_proxy.rb', line 120

def inspect
  load_target
  @target.inspect
end

#loadedObject



107
108
109
# File 'lib/active_record/associations/association_proxy.rb', line 107

def loaded
  @loaded = true
end

#loaded?Boolean

Returns:

  • (Boolean)


103
104
105
# File 'lib/active_record/associations/association_proxy.rb', line 103

def loaded?
  @loaded
end

#proxy_ownerObject



60
61
62
# File 'lib/active_record/associations/association_proxy.rb', line 60

def proxy_owner
  @owner
end

#proxy_reflectionObject



64
65
66
# File 'lib/active_record/associations/association_proxy.rb', line 64

def proxy_reflection
  @reflection
end

#proxy_respond_to?Object

:nodoc:



49
# File 'lib/active_record/associations/association_proxy.rb', line 49

alias_method :proxy_respond_to?, :respond_to?

#proxy_targetObject



68
69
70
# File 'lib/active_record/associations/association_proxy.rb', line 68

def proxy_target
  @target
end

#reloadObject



97
98
99
100
101
# File 'lib/active_record/associations/association_proxy.rb', line 97

def reload
  reset
  load_target
  self unless @target.nil?
end

#resetObject



92
93
94
95
# File 'lib/active_record/associations/association_proxy.rb', line 92

def reset
  @loaded = false
  @target = nil
end

#respond_to?(*args) ⇒ Boolean

Returns:

  • (Boolean)


72
73
74
# File 'lib/active_record/associations/association_proxy.rb', line 72

def respond_to?(*args)
  proxy_respond_to?(*args) || (load_target && @target.respond_to?(*args))
end

#targetObject



111
112
113
# File 'lib/active_record/associations/association_proxy.rb', line 111

def target
  @target
end

#target=(target) ⇒ Object



115
116
117
118
# File 'lib/active_record/associations/association_proxy.rb', line 115

def target=(target)
  @target = target
  loaded
end