Ruby on rails 很多非常相似的函数,意大利面代码修复?
我有大约11个如下所示的函数:Ruby on rails 很多非常相似的函数,意大利面代码修复?,ruby-on-rails,ruby,loops,ruby-on-rails-4,iteration,Ruby On Rails,Ruby,Loops,Ruby On Rails 4,Iteration,我有大约11个如下所示的函数: def pending_acceptance(order_fulfillments) order_fulfillments.each do |order_fulfillment| next unless order_fulfillment.fulfillment_time_calculator. pending_acceptance?; collect_fulfillments( order_fulfillment.
def pending_acceptance(order_fulfillments)
order_fulfillments.each do |order_fulfillment|
next unless order_fulfillment.fulfillment_time_calculator.
pending_acceptance?; collect_fulfillments(
order_fulfillment.status,
order_fulfillment
)
end
end
def pending_start(order_fulfillments)
order_fulfillments.each do |order_fulfillment|
next unless order_fulfillment.fulfillment_time_calculator.
pending_start?; collect_fulfillments(
order_fulfillment.status,
order_fulfillment
)
end
end
def order_fulfillment_check(method, order_fulfillment)
case method
when "picked_up" then return order_fulfillment.handed_over_late? && order_fulfillment.fulfillment_time_calculator.pending_handover?
...
... [more case statements] ...
...
else return order_fulfillment.fulfillment_time_calculator.send(method + "?")
end
end
def method_missing(method_name, args*, &block)
args[0].each do |order_fulfillment|
next unless order_fulfillment_check(method_name, order_fulfillment);
collect_fulfillments(
order_fulfillment.status,
order_fulfillment
)
end
end
def pending_acceptance(order_fulfillments)
order_fulfillments.select do |o|
o.fulfillment_time_calculator.pending_acceptance?
end
end
def picked_up(order_fulfillments)
order_fulfillments.select do |order_fulfillment|
order_fulfillment.handed_over_late? && order_fulfillment.
fulfillment_time_calculator.pending_handover?
end
end
def calling_code
# order_fulfillments = OrderFulFillments.get_from_somewhere
# Now, filter
collect_fulfillments(pending_start order_fulfillments)
collect_fulfillments(picked_up order_fulfillments)
end
def collect_fullfillments order_fulfillments
order_fulfillments.each {|of| collect_fullfillment(of) }
end
迭代总是相同的,但下一步是,除非
条件不同。如果你想知道:除非和,否则它是下一个因为RuboCop在抱怨它。有没有更好的解决方案?我讨厌这个意大利面代码。类似于将条件传递到“iterate_it”函数之类的东西
编辑:不能只传递另一个参数,因为有时条件是双重的:
def picked_up(order_fulfillments)
order_fulfillments.each do |order_fulfillment|
next unless
order_fulfillment.handed_over_late? && order_fulfillment.
fulfillment_time_calculator.pending_handover?
collect_fulfillments(
order_fulfillment.status,
order_fulfillment
)
end
end
edit2:还有一个问题:如何分割符号,从状态中获取用户角色?比如:
:deliver\u start=>:deliver或“deliver”
?您可以创建字符串数组
arr = ['acceptance','start', ...]
下一步:
arr.each do |method|
define_method ( 'pending_#{method}'.to_sym ) do |order_fulfillments|
order_fulfillments.each do |order_fulfillment|
next unless order_fulfillment.fulfillment_time_calculator.
send('pending_#{method}?'); collect_fulfillments(
order_fulfillment.status,
order_fulfillment
)
end
end
end
有关的详细信息,您可以使用类似于的方法\u missing
在课堂的最下面,写下如下内容:
def pending_acceptance(order_fulfillments)
order_fulfillments.each do |order_fulfillment|
next unless order_fulfillment.fulfillment_time_calculator.
pending_acceptance?; collect_fulfillments(
order_fulfillment.status,
order_fulfillment
)
end
end
def pending_start(order_fulfillments)
order_fulfillments.each do |order_fulfillment|
next unless order_fulfillment.fulfillment_time_calculator.
pending_start?; collect_fulfillments(
order_fulfillment.status,
order_fulfillment
)
end
end
def order_fulfillment_check(method, order_fulfillment)
case method
when "picked_up" then return order_fulfillment.handed_over_late? && order_fulfillment.fulfillment_time_calculator.pending_handover?
...
... [more case statements] ...
...
else return order_fulfillment.fulfillment_time_calculator.send(method + "?")
end
end
def method_missing(method_name, args*, &block)
args[0].each do |order_fulfillment|
next unless order_fulfillment_check(method_name, order_fulfillment);
collect_fulfillments(
order_fulfillment.status,
order_fulfillment
)
end
end
def pending_acceptance(order_fulfillments)
order_fulfillments.select do |o|
o.fulfillment_time_calculator.pending_acceptance?
end
end
def picked_up(order_fulfillments)
order_fulfillments.select do |order_fulfillment|
order_fulfillment.handed_over_late? && order_fulfillment.
fulfillment_time_calculator.pending_handover?
end
end
def calling_code
# order_fulfillments = OrderFulFillments.get_from_somewhere
# Now, filter
collect_fulfillments(pending_start order_fulfillments)
collect_fulfillments(picked_up order_fulfillments)
end
def collect_fullfillments order_fulfillments
order_fulfillments.each {|of| collect_fullfillment(of) }
end
根据您的需求,您可以检查方法名称是否以“pending”开头
请注意,此代码未经测试,但它应该在某个地方
另外,作为旁注,order\u fulfillment.fulfillment\u time\u calculator.some\u random\u method
实际上违反了。您可能需要解决此问题。当您使用另一个参数来决定要检查的条件时,可以传递该参数。只需将所有可能的条件作为lambda存储在散列中:
FULFILLMENT_ACTIONS = {
pending_acceptance: lambda { |fulfillment| fulfillment.fulfillment_time_calculator.pending_acceptance? },
pending_start: lambda { |fulfillment| fulfillment.fulfillment_time_calculator.pending_acceptance? },
picked_up: lambda { |fulfillment| fulfillment.handed_over_late? && fulfillment.fulfillment_time_calculator.pending_handover? }
}
def process_fulfillments(type, order_fulfillments)
condition = FULFILLMENT_ACTIONS.fetch(type)
order_fulfillments.each do |order_fulfillment|
next unless condition.call(order_fulfillment)
collect_fulfillments(order_fulfillment.status, order_fulfillment)
end
end
被称为:
process_fulfillments(:pending_acceptance, order_fulfillments)
process_fulfillments(:pending_start, order_fulfillments)
process_fulfillments(:picked_up, order_fulfillments)
虽然next
很方便,但它在代码中出现较晚(r),因此更难掌握。我会先在列表中选择,然后执行操作。(请注意,只有当您的“检查”没有像订单填写中那样的副作用时,这才可能。如果失败,请发送电子邮件并返回false)
<> P>所以如果测试是复杂的,我将通过表达选择标准来开始重构,然后拔出这些项目的处理(也会匹配您给出的方法名称),在中间的某个地方,它可能看起来是这样的:
def pending_acceptance(order_fulfillments)
order_fulfillments.each do |order_fulfillment|
next unless order_fulfillment.fulfillment_time_calculator.
pending_acceptance?; collect_fulfillments(
order_fulfillment.status,
order_fulfillment
)
end
end
def pending_start(order_fulfillments)
order_fulfillments.each do |order_fulfillment|
next unless order_fulfillment.fulfillment_time_calculator.
pending_start?; collect_fulfillments(
order_fulfillment.status,
order_fulfillment
)
end
end
def order_fulfillment_check(method, order_fulfillment)
case method
when "picked_up" then return order_fulfillment.handed_over_late? && order_fulfillment.fulfillment_time_calculator.pending_handover?
...
... [more case statements] ...
...
else return order_fulfillment.fulfillment_time_calculator.send(method + "?")
end
end
def method_missing(method_name, args*, &block)
args[0].each do |order_fulfillment|
next unless order_fulfillment_check(method_name, order_fulfillment);
collect_fulfillments(
order_fulfillment.status,
order_fulfillment
)
end
end
def pending_acceptance(order_fulfillments)
order_fulfillments.select do |o|
o.fulfillment_time_calculator.pending_acceptance?
end
end
def picked_up(order_fulfillments)
order_fulfillments.select do |order_fulfillment|
order_fulfillment.handed_over_late? && order_fulfillment.
fulfillment_time_calculator.pending_handover?
end
end
def calling_code
# order_fulfillments = OrderFulFillments.get_from_somewhere
# Now, filter
collect_fulfillments(pending_start order_fulfillments)
collect_fulfillments(picked_up order_fulfillments)
end
def collect_fullfillments order_fulfillments
order_fulfillments.each {|of| collect_fullfillment(of) }
end
你仍然会有11(+1)种方法,但我认为你应该更多地表达你的想法,而你的同事们也会对快速发生的事情感到惊讶。考虑到你的例子和问题,我认为你应该寻求一个简单、富有表现力的解决方案。如果您更“铁杆”,请使用其他解决方案中给出的更实用的lambda方法。另外,请注意,这些方法可以组合在一起(通过传递迭代器)。:再传递一个参数并将该参数用于条件。通过使用这种方法,您只需使用1个函数,而不是11个检查:)什么是+“?”
?你能在那里通过另一个条件吗?另外,&block
的作用是什么?这是当前方法的名称加上末尾添加的?
,就像在代码片段中一样<代码>&block
在这种情况下是不需要的,但是编写method\u missing
的一般约定,因为它将捕获所有未在类中定义的方法调用,即使是传递块的方法调用。看起来不错@斯皮克曼:我在“编辑2”中添加了一个小问题。请你看一下好吗?:)您可以首先将符号转换为字符串,从而对其进行切片::deliverer\u started.to\u.slice(“'u')。first#=>“deliverer”
。我不确定这与我的答案是否相符。很好。我不明白为什么这个回答被否决了。解决此重复问题的最佳解决方案是使用元编程,这就是此解决方案所做的。在理解提议的解决方案之前,请不要投反对票!理解问题并提出好的解决方案需要时间