Home > Back-end >  Ruby forwarding to a object returned by accessor method
Ruby forwarding to a object returned by accessor method

Time:04-22

I have a class with roughly the following structure:

class X
  def initialize
    @container = Container.new
    ....
  end
  def store
    @container.get_store
  end
  def f
    store.f
  end
  def g
    store.g
  end
  def h
    store.h
  end
  ....
end

As can be seen, I have a couple of methods, which simply "forward" to store, only that store is not an instance variable, but the result of a parameterless method. Is there a compact way to implement this forwarding? If store would always return the identical object, I could do something like this:

class X
  extend Forwardable
  def initialize
    container = Container.new
    @store = container.the_store
  end
  def_delegator :@store, .f, :g, :h
end

but I can't rely on this; @container.the_store may change during the lifetime of the instance. One alternative I considered is something like

class X
  [:f,:g,:h].each do |meth_sym|
    define_method(meth_sym) do |*args|
      store.public_send(meth_sym, *args)
    end
  end
  def store
    @container.get_store
  end
end

but this looks clumsy. Can anymody suggest a different solution for my problem?

CodePudding user response:

From the docs for Forwardable#def_instance_delegator:

accessor should be a method name, instance variable name, or constant name.

Examples: (both symbols and strings work and . is equivalent to ::)

def_delegator :@store, :f     # delegates f to instance variable @store
def_delegator :store, :f      # delegates f to instance method store
def_delegator 'X.store', :f   # delegates f to class method store
def_delegator 'X::Store', :f  # delegates f to constant X::Store

Since you have an instance method, you want :store (without @)

  •  Tags:  
  • ruby
  • Related