Ruby on rails 将方法委托给对象的Ruby模块

Ruby on rails 将方法委托给对象的Ruby模块,ruby-on-rails,ruby,rails-activerecord,metaprogramming,Ruby On Rails,Ruby,Rails Activerecord,Metaprogramming,我有一个名为Run的AR对象,它保存运行开始、结束、禁用等的信息。我试图创建一个类,并希望使其“可运行”。因此,我创建了一个名为Runnable的模块,它在初始化时接收一个run对象。现在假设我将这个模块混合到一个类中。我希望something对象将运行时定义的所有方法委托给run对象 module Runnable def initialize(run) @run = run end def self.method_missing(name, *args) sup

我有一个名为Run的AR对象,它保存运行开始、结束、禁用等的信息。我试图创建一个类,并希望使其“可运行”。因此,我创建了一个名为
Runnable
的模块,它在初始化时接收一个run对象。现在假设我将这个模块混合到一个类
中。我希望something对象将运行时定义的所有方法委托给run对象

module Runnable
  def initialize(run)
    @run = run
  end

  def self.method_missing(name, *args)
    super unless @run.respond_to?(name)
    @run.send(name, args)
  end
end

class Something
  include Runnable
end
现在如果我这样做:

run = Run.find(123)
run.start_date # works!
something = Something.new(run)
something.start_date # NoMethodError: undefined method `start_date' for #<Something:0x007fb4a276b0c0>
run=run.find(123)
run.start#u date#有效!
某物=某物。新的(运行)
something.start#u date#NoMethodError:for的未定义方法“start#u date”#

知道我错过了什么吗?有没有更好的方法来完成我想做的事情?

现在使用
可转发的

module Runnable
  extend Forwardable
  def_delegator :@run, :start_date, :end_date

  def initialize(run)
    @run = run
  end
end
在我看来,a将实现您在这里寻找的目标。

您有两个错误:

  • 方法\u缺少
    需要是实例方法,而不是类方法
  • @run.send(name,args)
    应该是
    @run.send(name,*args)
    。前者导致
    ArgumentError:当执行
    Run#start_date
    时,参数数量错误(给定1,预期为0)

类运行
def开始日期
“现在随时”
结束
结束
模块可运行
def初始化(运行)
@跑
结束
def方法_缺失(名称,*args)
超级,除非@run.response_?(姓名)
@run.send(名称,*args)
结束
结束
分类
包括可运行的
结束
run=run.new
run.start\u日期
#=>“随时都可以”
某物=某物。新的(运行)
#=> #
开始约会
#=>“随时都可以”

我考虑过这个问题,但我不能在模块中使用它,对吗?但我不确定您为什么要在这里使用模块。您在其中定义了initialize,这似乎不是一个非常灵活的模块。为什么不使用继承并执行
?因为我只有一次机会从类继承。一旦我的
Something
类继承了
Runnable
,它就不能继承其他任何东西。
class Run
  def start_date
    "Any time now"
  end
end

module Runnable
  def initialize(run)
    @run = run
  end

  def method_missing(name, *args)
    super unless @run.respond_to?(name)
    @run.send(name, *args)
  end
end

class Something
  include Runnable
end

run = Run.new
run.start_date
  #=> "Any time now"
something = Something.new(run)
  #=> #<Something:0x00000002642100 @run=#<Run:0x0000000266d558>>
something.start_date 
  #=> "Any time now"