【发布时间】:2015-05-26 12:10:17
【问题描述】:
已编辑
假设我有以下代码:
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
一些额外的限制:
- 我不想在
Kid和Teacher类中都添加compute方法。这是因为:- 我想尽可能保持干燥,其他几个类的对象也有
Calculators与之关联 - 这样做需要对我正在使用的遗留代码进行大规模重构(代码周围散布着许多
calculator.compute调用,通常以不太明显的方式调用)
- 我想尽可能保持干燥,其他几个类的对象也有
原版
如果我有
object.foo
那么self 在foo 的上下文中的值是object。但如果我有:
object.foo.bar
如何在bar 的定义中引用object? self 显然不起作用,因为它只是等于 object.foo 的返回值。
我无法更改foo 的实现。并且foo和bar不能在同一个类的对象上调用。
【问题讨论】:
-
"
self显然是行不通的,因为它只是等于object.foo" 的返回值。除非object.foo返回self,例如def foo; #some logic here; self; end;在这种情况下,#foo的返回值为object。或object.foo返回同一类的对象。以"String".gsub('St','B').downcase #=> 'bring'为例,因为 gsub 返回一个字符串,而 downcase 是一个字符串方法,所以虽然它不是作用于同一个字符串而是一个副本,但它仍然在对象String的上下文中。如果这没有帮助,我建议让您的问题更具体一些。 -
@engineersmnky:谢谢!不幸的是,我无法更改
foo的实现。刚刚更新了问题。不,object.foo不会返回与object相同类的对象。我也会澄清这一点。感谢您的反馈! -
这似乎是一个坏掉的设计。 binding_of_caller 可能会有所帮助
-
@FrederickCheung 谢谢!这可能确实有帮助。
标签: ruby-on-rails ruby metaprogramming