Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Delegate all method calls on a model to an association

Tags:

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).

like image 888
badawym Avatar asked Mar 28 '12 19:03

badawym


People also ask

What is method delegation?

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.

What does delegate do in Rails?

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.

What is Simpledelegator?

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.

What is Delegation in Ruby?

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.


2 Answers

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.

like image 179
Carlos J García Avatar answered Sep 20 '22 06:09

Carlos J García


There are two things you can do here:

  1. 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 
  2. 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.

like image 27
Veraticus Avatar answered Sep 20 '22 06:09

Veraticus