假设我有以下代码:
class Kid < ActiveRecord::Base
has_one :calculator
attr_accessible :favorite_num
end
class Teacher < ActiveRecord::Base
has_one :calculator
# does not have a favorite_num
end
class Calculator < ActiveRecord::Base
belongs_to :kid
belongs_to :teacher
def compute(number)
# takes the number passed in and multiplies it by
# the favorite_num if it exists, otherwise returns 42
end
end
我需要做的是定义上面的compute
,以便调用以下工作。
kid = Kid.first
=> #<User id: 1, favorite_num: 4, . . . >
kid.calculator.compute(5)
=> 20
teacher = Teacher.first
=> #<Teacher id: 1, . . . >
teacher.calculator.compute(5)
=> 42
一些额外的限制:
compute
和Kid
类中添加Teacher
方法。这是因为:
Calculators
相关联calculator.compute
个调用,通常以不太明显的方式调用)原始版本
如果我有
object.foo
然后self
上下文中foo
的值为object
。但是,如果我有:
object.foo.bar
如何在object
的定义中引用bar
? self
显然不会工作,因为它只等于object.foo
的返回值。
我无法更改foo
的实施。并且无法在同一类的对象上调用foo
和bar
。
答案 0 :(得分:0)
您描述的链接方法类型要求方法foo
返回self
。为了实现这一点,您必须更改方法定义或修改它。更改方法定义很简单,只需将self
写为方法的最后一个语句即可。当然,这意味着您无法从方法中返回任何其他内容,因此对于每种方法而言,它都不是可行的模式。我强烈建议不要使用猴子补丁,因为我认为由此产生的丑陋代码是不值得的。
然而,有一些解决这个问题的方法,不需要修改原始方法。最简单的解决方案是将方法调用写在彼此之下。它可能不那么“性感”,但它可以完成工作。
object.foo
object.bar
如果您想省略重复object
,可以使用Object#tap
。
object.tap{|o| o.foo }.bar
使用Symbol#to_proc
可以缩短一点。
object.tap(&:foo).bar