我正在使用庞大的遗留代码库,所以我正在寻找有关此特定问题的建议,而不是更好的高级实现的建议。
我正在使用的简化版本:
class Order < ActiveRecord::Base
has_many :line_items
#other stuff
def balance
#some definition
end
end
class LineItem < ActiveRecord::Base
belongs_to :order
#other stuff
end
module Concerns
module LineItems
module Aggregates
extend ActiveSupport::Concern
#stuff
def balance
#some other definition
end
end
end
end
Order有一个名为'balance'的方法,LineItem的一个模块也有一个名为'balance'的方法。似乎大部分时间(在代码库中的大多数地方),当调用specific_line_item.balance时,它使用LineItem模块下的方法定义,但是有几个地方它从Order调用方法。
Ruby / Rails中是否有任何方法可以在方法调用中指定我想使用哪两个?或者可能还有其他东西在这里,因为Ruby没有方法重载,所以我在这里描述的问题是不可能的?
调用任一方法的所有相关情况都来自line_item(即specific_line_item.balance),所以我认为它总是选择离家较近的方法,而不是进行关联跳转并调用Order的'balance'方法没有被告知。
修改 谢谢你的回复!我的问题似乎不够明确。我理解
之间的区别Order.first.balance
和
LineItem.first.balance
并且调用的balance方法是在该类的对象中定义的方法。在我所描述的情况中,我在实际的实时应用环境中观察到,在代码中的某个位置
LineItem.find(some_id).balance
被称为输出而不是由LineItem'balance'方法计算的结果,而是来自Order类的结果。
所以我希望得知有一些ruby怪癖可能会在某些条件下将对象称为同名的同名方法,而不是它自己的方法。但我认为这是不可能的,所以可能还有其他一些特定于此情况的内容。
答案 0 :(得分:0)
首先,ActiveRecord::Concern
可以改变很多行为并且你遗漏了很多代码,最重要的是,我不知道它被注入的地方,但是我可以做出有根据的猜测。
要使Concern
方法可用于给定对象,它必须是include
在对象类的正文中。
如果您有权访问Order
对象的实例,则可以随时调用balance
方法:
order = Orders.last # grab the last order in your database
order.balance # this will call Order#balance
如果你有Order
,那么你也可以获得LineItem
:
order.line_items.first.balance # should call the Concerns:: LineItems::Aggregates#balance
您可以打开一个Rails控制台(使用rails console
)并运行上面的代码,看它是否按预期工作。您需要一个有效的数据库才能获得有意义的订单和余额,您可能需要四处寻找已完成的订单,但Ruby完全是为了探索而且还有一个REPL。
我还grep
(或ag
或ack
)寻找balance
调用的代码库可能会执行类似grep -r "(^|\s)\w+\.balance" *
的操作,你想要找的是之前的 .balance
这个词,它是&#34;余额的接收者&#34;消息,如果该接收者是Order
对象,则会调用Order#balance
,如果它是LineItem
对象,则会调用Concerns:: LineItems::Aggregates#balance
。
我觉得你并不熟悉Ruby的范例,如果是这样,那么一个例子可能有所帮助。
让我们定义两个简单的Ruby对象:
class Doorman
def greet
puts "Good day to you sir!"
end
end
class Bartender
def greet
puts "What are you drinking?"
end
end
Doorman
和Bartender
都有greet
方法,并且调用该方法取决于我们称之为greet
的对象。
# Here we instantiate one of each
a_doorman = Doorman.new
a_bartender = Bartender.new
a_doorman.greet # outputs "Good day to you sir!"
a_bartender.greet # outputs "What are you drinking?"
我们仍在使用名为greet
的方法,但接收方决定了哪个被调用。
Ruby是一种传递语言的消息&#34;和每个&#34;方法&#34;它不是一个函数,而是一个传递给对象并由该对象处理的消息。
<强>参考强>