Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ruby-on-rails/57.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby on rails 很多非常相似的函数,意大利面代码修复?_Ruby On Rails_Ruby_Loops_Ruby On Rails 4_Iteration - Fatal编程技术网

Ruby on rails 很多非常相似的函数,意大利面代码修复?

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.

我有大约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.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
迭代总是相同的,但下一步是
,除非
条件不同。如果你想知道:除非和
,否则它是下一个

编辑:不能只传递另一个参数,因为有时条件是双重的:

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”
。我不确定这与我的答案是否相符。很好。我不明白为什么这个回答被否决了。解决此重复问题的最佳解决方案是使用元编程,这就是此解决方案所做的。在理解提议的解决方案之前,请不要投反对票!理解问题并提出好的解决方案需要时间