我想将Bar上的类方法委托给Foo类的实例,但是我无法让代理工作。没有任何委托方法抛出错误,getters只返回nil。这是我的代码的样子:
class Foo
attr_reader :worksheet_id, :access_token
def configure worksheet_id: raise, access_token: raise
@worksheet_id = worksheet_id
@access_token = access_token
end
end
class Bar
class << self
extend Forwardable
def_delegators Foo.new, :configure, :worksheet_id, :access_token
end
configure worksheet_id: 1, access_token: 2
end
这就是我希望能够做到的。
Bar.worksheet_id # => returns nil, should be 1.
Bar.access_token # => returns nil, should be 2.
我做错了什么?
答案 0 :(得分:3)
def_delegator
系列方法的第一个参数是Symbol
或String
(或其他任何实现to_s
的),表示“访问者”,访问委派目标。它不是 委托目标本身。
所以,这样的事情会奏效:
class Bar
class << self
extend Forwardable
def_delegators :@foo, :configure, :worksheet_id, :access_token
end
@foo = Foo.new
configure worksheet_id: 1, access_token: 2
end
Bar.worksheet_id # => 1
Bar.access_token # => 2
实际发生的是,forwardable
库使用字符串插值来构建转发器方法的定义,然后eval
d。
从本质上讲,它看起来像这样:
"#{target}.__send__(#{method})"
因此,您可以传递target
的任何内容,to_s
会产生eval
的结果,然后调用__send__
。但是,在您的情况下,Foo.new.to_s
类似#<Foo:0x007fc4aa521ab8>
。当插入字符串和eval
d时,该行以#
字符开头,或者简单地说:转发器方法由一行注释掉!这就是它返回nil
的原因,因为这是一个空方法返回的原因。