Rails 4.0.3:after_save回调似乎太快了?

时间:2014-07-17 10:46:55

标签: activerecord ruby-on-rails-4 callback

鉴于以下两个类Customer和Order,我遇到了一个问题,我已经缩小到我正在使用的回调的执行时间。

使用回调的原因是我需要存储每个客户的聚合差异,而不必每次都迭代他/她的所有订单。所以我意识到在每次保存之前使用回调来首先更新每个单独订单上的差异可能是一个很好的方法,其次,在之后更新客户模型上的聚合差异保存每个订单。

我得到的症状是奇怪的看似随机的错误,它告诉我两个订单之间的差异,总计238美元是15美元。当我将调试器限制在受影响的客户时,我意识到它只是跳过下面的orders.each循环(但仅在某些情况下),因为没有与客户关联的订单。

由于所有客户至少有一个订单,并且订单实际上是在此系统中的客户之前创建的,因此无法实现。

在ActiveRecord完成保存Order对象并更新与Customer模型的关系之前,我是否可以通过某种方式强制执行after_save回调?

正如你所看到的那样,我还试着用一个计时器来看看我是否可以通过在继续之前暂停线程来开始工作,但这不起作用。

class Customer < ActiveRecord::Base

  ...

  has_many :orders
  before_save :calculate_shipping

  def update_total_diff
    sum = 0

    orders.each do |o|
      if o.diff.present?
        sum += o.diff
      end
    end

    # HERE IS THE PROBLEM: When inspecting the orders collection in the debuggger it is empty.

    # Make sure shipping is updated
    calculate_shipping

    # Since we are calculating the diff shipping must be subtracted
    sum -= shipping

    self.total_diff = sum
    self.save
  end

  ...

  private

    def calculate_shipping

      ...returns either 15 or 0

    end

end

订单模型:

class Order < ActiveRecord::Base

  ...

  belongs_to :customer
  before_save :update_diff
  after_save :update_customer

private
  def update_diff

    #Updates a local value
    ......

  end

  def update_customer

      #Here we trigger a function on the customer model in order to tell it that it needs to re-calculate

      sleep(1/10) #Tried this to test - no luck

      if self.customer_id.present? && diff.present?
        self.customer.update_total_diff
    end
  end
end

编辑:

看看这个:

From: /vagrant/app/models/order.rb @ line 23 Order#update_customer:

    21: def update_customer
    22:   if self.customer_id.present?
 => 23:     binding.pry
    24:   end
    25:     if self.customer_id.present? && diff.present?
    26:     self.customer.update_total_diff
    27:   end
    28: end

...

[4] pry(#<Order>)> michael = self.customer
=> #<Customer id: 2, name: "Michael xxx", mail: "xxx@gmail.com", shipping_address_id: 2, created_at: "2014-07-17 11:00:12", updated_at: "2014-07-17 11:00:12", shipping: #<BigDecimal:7fada4e707d0,'0.0',9(36)>, total_diff: nil>
[5] pry(#<Order>)> michael.orders
=> []
[6] pry(#<Order>)> michael = Customer.find(2)
=> #<Customer id: 2, name: "Michael xxx", mail: "xxx@gmail.com", shipping_address_id: 2, created_at: "2014-07-17 11:00:12", updated_at: "2014-07-17 11:00:12", shipping: #<BigDecimal:7fada5008098,'0.0',9(36)>, total_diff: nil>
[7] pry(#<Order>)> michael.orders
=> [#<Order id: 2, pledge_id: 4808304, amount: #<BigDecimal:7fada50fc120,'0.89E2',9(36)>, customer_id: 2, perk_id: 9, created_at: "2013-11-23 00:00:00", updated_at: "2014-07-17 11:00:12", diff: #<BigDecimal:7fada5108240,'0.0',9(36)>>]
[8] pry(#<Order>)>

我尝试在Order命令客户重新计算之前停止我的调试器。我尝试将同一个客户两次分配给变量&#34; michael&#34;。如果我简单地用以下内容分配变量:     michael = self.customer 该对象不知道其任何相关订单。如果我像这样分配它像activerecord:     michael = Customer.find(2) 它会工作。那是为什么?

现在我设法解决了这个问题,但我还是想知道是否有人可以为我解释这种情况?

me = Customer.find(id)

me.orders.each do |o|
  if o.diff.present?
    sum += o.diff
  end
end

0 个答案:

没有答案