I have an AR object called Run that keeps information of when the run was started, ended, disabled, etc. I am trying to create a class Something and want to make it "runnable". So I created a module called Runnable
that takes in a run object on initialization. Now say I mix in this module into a class Something
. I want the something object to delegate all the methods defined on run to the run object.
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
Now if I do:
run = Run.find(123)
run.start_date # works!
something = Something.new(run)
something.start_date # NoMethodError: undefined method `start_date' for #<Something:0x007fb4a276b0c0>
Any idea what I am missing? Is there a better way of doing what I am trying to do?
在我看来, SimpleDelegator可以实现您在这里寻找的东西。
You have two mistakes:
method_missing
needs to be an instance method, not a class method @run.send(name, args)
should be @run.send(name, *args)
. The former results in ArgumentError: wrong number of arguments (given 1, expected 0)
when Run#start_date
is executed. 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"
Using Forwardable
for now
module Runnable
extend Forwardable
def_delegator :@run, :start_date, :end_date
def initialize(run)
@run = run
end
end
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.