完成后如何在循环中检查状态的结果?

时间:2019-08-24 02:20:51

标签: ruby-on-rails ruby

我有一个循环,可为订单下的任何购买创建退款。

订单可以有多笔付款(如果用户升级运输,在初次付款后将商品添加到购物车并重新提交等),这在电子商务中并不是很麻烦,但在这种情况下是必需的。

我有这个循环:

orders_payments = Payment.where()
  orders_payments.each do |btp|
    transaction = gateway.transaction.find("#{btp.transaction_token}")
    if transaction.status == "submitted_for_settlement"
      void = gateway.transaction.void("#{btp.transaction_token}")
      if void.success?
        format.html { redirect_to user_orders_path, notice: 'Order refund was successfully refunded.' }
      else
        format.html { redirect user_orders_path, notice: 'Order refund unsuccessful.' }
      end
    elsif transaction.status == "settled"
      refund = gateway.transaction.refund("#{btp.transaction_token}")
      if refund.success?
         format.html { redirect_to user_orders_path, notice: 'Order refund was successfully refunded.' }
      else
         format.html { redirect user_orders_path, notice: 'Order refund unsuccessful.' }
      end
    end
  end

当然,由于重定向,这不起作用。但是除了不创建重定向之外,而且重要的是我有一个带有状态消息的重定向...如何在创建循环后检查无效状态或退款的状态。

我希望能够检查哪些有效,哪些无效。

关于如何做到这一点的任何想法?

3 个答案:

答案 0 :(得分:2)

您可以使用多个循环将数据分为几类,而不是一个循环。

迭代的第一步是检索transaction对象。也可以使用map

transactions = orders_payments.map do |btp|
  gateway.transaction.find("#{btp.transaction_token}")
end

下一步是if语句,该语句根据数据的状态将其分为两组。您可以使用select来构造这两个列表:

submitted = transactions.select do |transaction|
  transaction.status == "submitted_for_settlement"
end
settled = transactions.select do |transaction|
  transaction.status == "settled"
end

下一步是处理两个列表,并跟踪成功或失败的列表。听起来像到此结束时,您想要每个事务组的“成功”和“失败”列表,剩下4个列表。 partition是此用例的好方法:

successful_submitted, failed_submitted = submitted.partition do |transaction|
  gateway.transaction.void("#{btp.transaction_token}").success?
end
successful_settled, failed_settled = settled.partition do |transaction|
  gateway.transaction.refund("#{btp.transaction_token}").success?
end

答案 1 :(得分:1)

您可以使用each_with_object存储状态。在这里,我将它们存储在transaction_token的哈希中。

请注意,我使用的是find_each而不是each,以避免立即将所有记录拖入内存。

transaction_statuses = orders_payments.find_each.each_with_object({}) do |btp,status|
  transaction = gateway.transaction.find("#{btp.transaction_token}")
  status[btp.transaction_token] = case
  when transaction.status == "submitted_for_settlement"
    { voided: gateway.transaction.void("#{btp.transaction_token}") }
  when transaction.status == "settled"
    { refunded: gateway.transaction.refund("#{btp.transaction_token}") }
  end
end

然后稍后对它们进行处理。

transaction_statuses.each do |token,status|
  case
  when status[:voided]
    case
    when status[:voided].success?
      puts "Order #{token} was successfully voided."
    else
      puts "Order #{token} void failed."
    end
  when status[:refunded]
    case
    when status[:refunded].success?
      puts "Order #{token} was successfully refunded."
    else
      puts "Order #{token} refund failed."
    end
  end
end

答案 2 :(得分:1)

如果您是因为遇到相同或相似的问题而来这里,在阅读此书之前,我建议您阅读max pleaner和Schwern关于该问题的答案。

以下方法可以工作,但可能是我做自己想做的事情的一个非常初学者的方法。

我创建了一个空白数组,然后使用flash.keep将消息存储在其中,然后在循环完成所有消息(无论退款成功还是退款)后重定向。

orders_payments = Payment.where()
messages = []
  orders_payments.each do |btp|
    transaction = gateway.transaction.find("#{btp.transaction_token}")
    if transaction.status == "submitted_for_settlement"
      void = gateway.transaction.void("#{btp.transaction_token}")
      if void.success?
         messages << "Refund Successful message"
      else
         messages << "Refund unSuccessful message"
      end
    elsif transaction.status == "settled"
      refund = gateway.transaction.refund("#{btp.transaction_token}")
      if refund.success?
         messages << "Refund successful message"
      else
         messages << "Refund unSuccessful message"
      end
    end
  end
  flash.keep[:notice] = messages.join if messages.any?
  respond_to do |format|
    format.html { redirect_to route }
  end
  ...