I am writing some rails code that uses proxy objects around ActiveRecord models. However, whenever a Class Method is called on an ActiveRecord::Relation
or ActiveRecord::Associations::CollectionProxy
, the value of self
is the original ActiveRecord class as opposed to the relation. For example:
class Blah < ActiveRecord::Base
def self.thing
MyProxyObject.new(self)
end
end
Blah.thing #<MyProxyObject @wrapped=Blah>
Blah.where(:column => 'value').thing #<MyProxyObject @wrapped=ActiveRecord::Relation>
Desired functionality would be that the wrapped object in the second case would be the ActiveRecord::Relation
object returned by Blah.where
. Is there an easy way of achieving this?
Something along the lines of
class Blah < ActiveRecord::Base
def self.thing
MyProxyObject.new(all)
end
end
works for me (prior to rails 4, use scoped
rather than all):
Blah.where(:foo => 1).thing
results in the proxy object holding a relation with the appropriate conditions applied.
@FrederickCheung answer is the Right Way To Go. I post this answer to explain why it is happenning.
The mystery sits in active_record/relation/delegation.rb
file:
def self.delegate_to_scoped_klass(method)
if method.to_s =~ /\A[a-zA-Z_]\w*[!?]?\z/
module_eval <<-RUBY, __FILE__, __LINE__ + 1
def #{method}(*args, &block)
scoping { @klass.#{method}(*args, &block) }
end
RUBY
else
module_eval <<-RUBY, __FILE__, __LINE__ + 1
def #{method}(*args, &block)
scoping { @klass.send(#{method.inspect}, *args, &block) }
end
RUBY
end
end
As you can see it defines a new method on the relation object, which is just delegating it to the class, hence self
is always a class itself here.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With