Activerecord Rails 4.0.3:after_save回调调用得太早了吗?
考虑到下面两个类Customer和Order,我有一个问题,我已经将问题缩小到我正在使用的回调的执行时间 使用回调的原因是,我需要存储每个客户的聚合差异,而不必每次迭代他/她的所有订单。因此,我意识到使用回调可能是一种好方法,首先在每次保存之前更新每个订单上的差异,然后在每次保存订单之后更新客户模型上的聚合差异 我得到的症状是奇怪的、看似随机的错误,它告诉我两份订单之间的差额(总计238美元)是15美元。当我将调试器限制在受影响的客户时,我意识到它只是跳过下面的orders.each循环(但仅在某些情况下),因为没有与客户关联的订单 因为所有客户都至少有一个订单,而且在这个系统中,订单实际上是在客户之前创建的,所以这不可能是真的 在ActiveRecord完成保存订单对象和更新与客户模型的关系之前,是否有某种方法可以强制执行after_save回调函数不被调用 正如您所看到的,我还尝试使用计时器来查看是否可以在继续之前让线程休眠一段时间来开始工作,但这不起作用Activerecord Rails 4.0.3:after_save回调调用得太早了吗?,activerecord,ruby-on-rails-4,callback,Activerecord,Ruby On Rails 4,Callback,考虑到下面两个类Customer和Order,我有一个问题,我已经将问题缩小到我正在使用的回调的执行时间 使用回调的原因是,我需要存储每个客户的聚合差异,而不必每次迭代他/她的所有订单。因此,我意识到使用回调可能是一种好方法,首先在每次保存之前更新每个订单上的差异,然后在每次保存订单之后更新客户模型上的聚合差异 我得到的症状是奇怪的、看似随机的错误,它告诉我两份订单之间的差额(总计238美元)是15美元。当我将调试器限制在受影响的客户时,我意识到它只是跳过下面的orders.each循环(但仅在
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>)>
me = Customer.find(id)
me.orders.each do |o|
if o.diff.present?
sum += o.diff
end
end