Class: ActiveRecord::Associations::CollectionProxy
- Inherits:
-
Object
- Object
- ActiveRecord::Associations::CollectionProxy
- Defined in:
- lib/active_record/associations/collection_proxy.rb
Overview
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.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
- #<<(*records) ⇒ Object (also: #push)
-
#===(other) ⇒ Object
Forwards
===
explicitly to the target because the instance method removal above doesn’t catch it. - #clear ⇒ Object
-
#initialize(association) ⇒ CollectionProxy
constructor
A new instance of CollectionProxy.
- #method_missing(method, *args, &block) ⇒ Object
- #proxy_association ⇒ Object
- #proxy_owner ⇒ Object
- #proxy_reflection ⇒ Object
- #proxy_target ⇒ Object
- #reload ⇒ Object
- #respond_to?(name, include_private = false) ⇒ Boolean
- #scoped ⇒ Object
- #to_ary ⇒ Object (also: #to_a)
Constructor Details
#initialize(association) ⇒ CollectionProxy
Returns a new instance of CollectionProxy.
60 61 62 63 |
# File 'lib/active_record/associations/collection_proxy.rb', line 60 def initialize(association) @association = association Array.wrap(association.[:extend]).each { |ext| proxy_extend(ext) } end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(method, *args, &block) ⇒ Object
84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 |
# File 'lib/active_record/associations/collection_proxy.rb', line 84 def method_missing(method, *args, &block) match = DynamicFinderMatch.match(method) if match && match.instantiator? send(:find_or_instantiator_by_attributes, match, match.attribute_names, *args) do |r| proxy_association.send :set_owner_attributes, r proxy_association.send :add_to_target, r yield(r) if block_given? end end if target.respond_to?(method) || (!proxy_association.klass.respond_to?(method) && Class.respond_to?(method)) if load_target if target.respond_to?(method) target.send(method, *args, &block) else begin super rescue NoMethodError => e raise e, e..sub(/ for #<.*$/, " via proxy for #{target}") end end end else scoped.readonly(nil).send(method, *args, &block) end end |
Instance Method Details
#<<(*records) ⇒ Object Also known as: push
123 124 125 |
# File 'lib/active_record/associations/collection_proxy.rb', line 123 def <<(*records) proxy_association.concat(records) && self end |
#===(other) ⇒ Object
Forwards ===
explicitly to the target because the instance method removal above doesn’t catch it. Loads the target if needed.
114 115 116 |
# File 'lib/active_record/associations/collection_proxy.rb', line 114 def ===(other) other === load_target end |
#clear ⇒ Object
128 129 130 131 |
# File 'lib/active_record/associations/collection_proxy.rb', line 128 def clear delete_all self end |
#proxy_association ⇒ Object
67 68 69 |
# File 'lib/active_record/associations/collection_proxy.rb', line 67 def proxy_association @association end |
#proxy_owner ⇒ Object
138 139 140 141 142 143 144 145 |
# File 'lib/active_record/associations/collection_proxy.rb', line 138 def proxy_owner ActiveSupport::Deprecation.warn( "Calling record.#{@association.reflection.name}.proxy_owner is deprecated. Please use " \ "record.association(:#{@association.reflection.name}).owner instead. Or, from an " \ "association extension you can access proxy_association.owner." ) proxy_association.owner end |
#proxy_reflection ⇒ Object
156 157 158 159 160 161 162 163 |
# File 'lib/active_record/associations/collection_proxy.rb', line 156 def proxy_reflection ActiveSupport::Deprecation.warn( "Calling record.#{@association.reflection.name}.proxy_reflection is deprecated. Please use " \ "record.association(:#{@association.reflection.name}).reflection instead. Or, from an " \ "association extension you can access proxy_association.reflection." ) proxy_association.reflection end |
#proxy_target ⇒ Object
147 148 149 150 151 152 153 154 |
# File 'lib/active_record/associations/collection_proxy.rb', line 147 def proxy_target ActiveSupport::Deprecation.warn( "Calling record.#{@association.reflection.name}.proxy_target is deprecated. Please use " \ "record.association(:#{@association.reflection.name}).target instead. Or, from an " \ "association extension you can access proxy_association.target." ) proxy_association.target end |
#reload ⇒ Object
133 134 135 136 |
# File 'lib/active_record/associations/collection_proxy.rb', line 133 def reload proxy_association.reload self end |
#respond_to?(name, include_private = false) ⇒ Boolean
78 79 80 81 82 |
# File 'lib/active_record/associations/collection_proxy.rb', line 78 def respond_to?(name, include_private = false) super || (load_target && target.respond_to?(name, include_private)) || proxy_association.klass.respond_to?(name, include_private) end |
#scoped ⇒ Object
71 72 73 74 75 76 |
# File 'lib/active_record/associations/collection_proxy.rb', line 71 def scoped association = @association association.scoped.extending do define_method(:proxy_association) { association } end end |
#to_ary ⇒ Object Also known as: to_a
118 119 120 |
# File 'lib/active_record/associations/collection_proxy.rb', line 118 def to_ary load_target.dup end |