当链接方法时,子方法可以访问和使用 'parent' 方法的结果吗? (即 Object.parent.child)
When chaining methods can the child method access and use the results of the 'parent' method? (i.e. Object.parent.child)
描述
我创建了一个 Report
对象,它具有不同的 environments/groups (:live & :demo),它们只是数组,将填充 ReportItem
具有以下属性的对象 :currency, :gross, :net
(并且毛额和净额持有 Ruby 货币对象)。
在Report.rb
class中有两个方法叫做add_money_to_net
和add_money_to_gross
都有一个变量我暂时命名为@group
问题
(report = Report.new
)
我想要做的是像这样的链式方法 report.demo.add_money_to_gross(<params>)
如果调用此方法我想访问 report.demo
(代替我的 @group
变量)。或者调用 report.live.add_money_to_gross(<params>)
应该让我访问 report.live
。这可能吗?
我希望这是有道理的。如果有任何不清楚的地方,请告诉我。
Report.rb
class Report
include ActiveModel::Model
attr_accessor :demo, :live
def initialize
@demo = []
@live = []
end
def demo
@demo
self
end
def live
@live
self
end
def add_money_to_net(money)
add_money(group: @group, money: money)
end
def add_money_to_gross(money)
add_money(group: @group, money: money)
end
private
def add_money(group:, money:)
item = group.find {|s| s.currency == money.currency }
if item
item.net += money
else
group << ReportItem.new(currency: money.currency.to_s, net: money)
end
end
end
ReportItem.rb
class ReportItem
include ActiveModel::Model
attr_accessor :currency, :gross, :net
def initialize(currency:, gross: nil, net: nil)
@currency = currency
@gross = gross ? gross : Money.new(0, currency)
@net = net ? net : Money.new(0, currency)
end
def gross=(value)
@gross = value if @gross.currency == @currency
end
def net=(value)
@net = value if @net.currency == @currency
end
end
我明白你想做什么,几乎就像命令行管道操作一样。而且,不,你的方法不可能(或者,恕我直言,推荐)。
考虑演示方法:
def demo
@demo
self
end
@demo
行确实是空操作。你不是 "returning" 这里的任何东西,没有分配任何东西,它只是......那里。 return这里唯一的东西就是自己。
现在,您可以执行以下操作:
def demo
@group = @demo
self
end
然后打电话
report.live.add_money_to_gross(money)
现在它应该可以正常工作了。在这里,live
和 demo
更像是状态管理器,在调用操作方法之前设置 @group
的状态。
也就是说,这有点脆弱,需要您按特定顺序调用事物,而临时变量似乎是一个等待发生的陷阱。为什么?因为这样调用:
report.add_money_to_gross(money)
是一个有效的调用,但除非首先调用了 live
或 demo
,否则不应如此。不会抛出任何错误,它只会添加到最后设置的 @group
中。
相反,实际上创建一个新对象来封装所有这些对我来说更有意义:
class ReportItemArray < Array
def add_money_to_net money
item = find_item(money)
if item
item.net += money
else
self << ReportItem.new(currency: money.currency.to_s, net: money)
end
end
def add_money_to_gross money
item = find_item(money)
if item
item.gross += money
else
self << ReportItem.new(currency: money.currency.to_s, gross: money)
end
end
def find_item money
self.find {|s| s.currency == money.currency }
end
end
然后,在你的报告中class:
class Report
def initialize
@demo = ReportItemArray.new
@live = ReportItemArray.new
end
def live
@live
end
def demo
@demo
end
end
请注意,live
和 demo
这两种方法现在实际上已经过时了,因为您使用 attr_accessor
并且它们不再 return 有什么特别之处,所以您实际上不需要覆盖它们,只是为了明确。 live
和 demo
对象本身仍然是数组,因此应该与您的其余代码兼容,但是 add_money
方法也附加到这些数组对象,所以现在您可以做:
report.live.add_money_to_gross(money)
现在通过调用 live
,您将获得数组,并且由于方法是该数组对象的一部分,您不再需要传递上下文,它们本身就知道它(group
变成 self
)。因此,调用方法作用于给定的数组。
这样做消除了调用 report.add_money_to_gross
的可能性(如果这样做会引发错误),这很好,因为这里的调用需要更多上下文(组)才能完成。这也消除了操作顺序冲突,因为不再需要状态。
最后一个不相关的说明,您可能已经注意到我上面对此的修复,但是您的 add_money
方法总是添加到 ReportItem
的 net
,即使原始调用是由 add_money_to_gross
.
制成
描述
我创建了一个 Report
对象,它具有不同的 environments/groups (:live & :demo),它们只是数组,将填充 ReportItem
具有以下属性的对象 :currency, :gross, :net
(并且毛额和净额持有 Ruby 货币对象)。
在Report.rb
class中有两个方法叫做add_money_to_net
和add_money_to_gross
都有一个变量我暂时命名为@group
问题
(report = Report.new
)
我想要做的是像这样的链式方法 report.demo.add_money_to_gross(<params>)
如果调用此方法我想访问 report.demo
(代替我的 @group
变量)。或者调用 report.live.add_money_to_gross(<params>)
应该让我访问 report.live
。这可能吗?
我希望这是有道理的。如果有任何不清楚的地方,请告诉我。
Report.rb
class Report
include ActiveModel::Model
attr_accessor :demo, :live
def initialize
@demo = []
@live = []
end
def demo
@demo
self
end
def live
@live
self
end
def add_money_to_net(money)
add_money(group: @group, money: money)
end
def add_money_to_gross(money)
add_money(group: @group, money: money)
end
private
def add_money(group:, money:)
item = group.find {|s| s.currency == money.currency }
if item
item.net += money
else
group << ReportItem.new(currency: money.currency.to_s, net: money)
end
end
end
ReportItem.rb
class ReportItem
include ActiveModel::Model
attr_accessor :currency, :gross, :net
def initialize(currency:, gross: nil, net: nil)
@currency = currency
@gross = gross ? gross : Money.new(0, currency)
@net = net ? net : Money.new(0, currency)
end
def gross=(value)
@gross = value if @gross.currency == @currency
end
def net=(value)
@net = value if @net.currency == @currency
end
end
我明白你想做什么,几乎就像命令行管道操作一样。而且,不,你的方法不可能(或者,恕我直言,推荐)。
考虑演示方法:
def demo
@demo
self
end
@demo
行确实是空操作。你不是 "returning" 这里的任何东西,没有分配任何东西,它只是......那里。 return这里唯一的东西就是自己。
现在,您可以执行以下操作:
def demo
@group = @demo
self
end
然后打电话
report.live.add_money_to_gross(money)
现在它应该可以正常工作了。在这里,live
和 demo
更像是状态管理器,在调用操作方法之前设置 @group
的状态。
也就是说,这有点脆弱,需要您按特定顺序调用事物,而临时变量似乎是一个等待发生的陷阱。为什么?因为这样调用:
report.add_money_to_gross(money)
是一个有效的调用,但除非首先调用了 live
或 demo
,否则不应如此。不会抛出任何错误,它只会添加到最后设置的 @group
中。
相反,实际上创建一个新对象来封装所有这些对我来说更有意义:
class ReportItemArray < Array
def add_money_to_net money
item = find_item(money)
if item
item.net += money
else
self << ReportItem.new(currency: money.currency.to_s, net: money)
end
end
def add_money_to_gross money
item = find_item(money)
if item
item.gross += money
else
self << ReportItem.new(currency: money.currency.to_s, gross: money)
end
end
def find_item money
self.find {|s| s.currency == money.currency }
end
end
然后,在你的报告中class:
class Report
def initialize
@demo = ReportItemArray.new
@live = ReportItemArray.new
end
def live
@live
end
def demo
@demo
end
end
请注意,live
和 demo
这两种方法现在实际上已经过时了,因为您使用 attr_accessor
并且它们不再 return 有什么特别之处,所以您实际上不需要覆盖它们,只是为了明确。 live
和 demo
对象本身仍然是数组,因此应该与您的其余代码兼容,但是 add_money
方法也附加到这些数组对象,所以现在您可以做:
report.live.add_money_to_gross(money)
现在通过调用 live
,您将获得数组,并且由于方法是该数组对象的一部分,您不再需要传递上下文,它们本身就知道它(group
变成 self
)。因此,调用方法作用于给定的数组。
这样做消除了调用 report.add_money_to_gross
的可能性(如果这样做会引发错误),这很好,因为这里的调用需要更多上下文(组)才能完成。这也消除了操作顺序冲突,因为不再需要状态。
最后一个不相关的说明,您可能已经注意到我上面对此的修复,但是您的 add_money
方法总是添加到 ReportItem
的 net
,即使原始调用是由 add_money_to_gross
.