I am having an ActiveRecord model with a polymorphic association like this:
class Reach < ActiveRecord::Base belongs_to :reachable, :polymorphic => true end
This model acts like a proxy. What I need to do is to forward all method calls on that object to the associated object :reachable
. I think delegate
won't help here because I have to explicitly name all the methods I need to delegate. I need something like delegate :all
to delegate all methods (not all
method).
A delegate is a type that represents references to methods with a particular parameter list and return type. When you instantiate a delegate, you can associate its instance with any method with a compatible signature and return type. You can invoke (or call) the method through the delegate instance.
On the Profile side we use the delegate method to pass any class methods to the User model that we want access from our User model inside our Profile model. The delegate method allows you to optionally pass allow_nil and a prefix as well. Ultimately this allows us to query for data in custom ways.
A concrete implementation of Delegator , this class provides the means to delegate all supported method calls to the object passed into the constructor and even to change the object being delegated to at a later time with #__setobj__. class User def born_on Date.
The delegate method takes a prefix argument, which allows you to append a prefix to the method names. Example: class Computer delegate :read, :write, prefix: "memory", to: :@memory def initialize @memory = Memory.new end end.
Since Rails 5.1+ you can delegate everything not implemented with delegate_missing_to :reachable
Basically, do what you expect. You could read more on the Api Doc
If you are stuck in a previous version then just recommend using the method_missing
from @Veraticus answer, is less performance-wise as mentioned but I think is the more flexible approach.
There are two things you can do here:
The slower (performance-wise) but easier method is to use method_missing:
class Reach < ActiveRecord::Base def method_missing(method, *args) return reachable.send(method, *args) if reachable.respond_to?(method) super end end
The faster performing method would be to define each method dynamically that you want to delegate:
class Reach < ActiveRecord::Base [:all, :my, :methods, :here].each do |m| define_method(m) do |*args| reachable.send(m, *args) end end end
You could even use that method in a more dynamic manner, if you wanted, by taking the Reach class, finding the methods that are defined on it and it alone, and defining only those on Reachable. I would do it by hand though because there are some you probably won't want to include.
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