【问题标题】:Using ActiveRecord callbacks使用 ActiveRecord 回调
【发布时间】:2021-02-18 17:03:44
【问题描述】:

使用 Rails 6 和 Ruby 2.7

我使用回调运行计算,它适用于创建;但是,这不适用于更新。除非标记为完成,否则我的计算会陷入循环。因此,为了编辑/更新,我尝试使用 before_update 将完成标记为假,然后运行与创建相同的计算,然后将其标记回真。我可以让它打破循环并更新属性,但是,它不像在创建时那样运行计算。

我一直在尝试很多变体来让它发挥作用,但我完全迷失了方向。我尝试了各种回调并浏览了文档并一直在寻找答案。如果有人可以给我一个线索,提示或任何见解,请。我没有收到任何类型的错误。

对于 .previous 方法,我使用的是 By_star gem,对于 .second_to_last 方法,我使用的是 groupdate gem。

感谢您的宝贵时间。

  belongs_to :user
  belongs_to :store
  after_create :create_calculations
  before_update :before_update_calculations
  after_update :update_calculations

def create_calculations
    store = Store.find(self.store_id)
    sheet = Sheet.find(self.id)
    past_sheet = store.sheets.second_to_last

  unless store.sheets.last
     s = past_sheet.draw - sheet.returned
  else
   s = sheet.sold
  end

  unless past_sheet
   s = store.sheets.last.draw - sheet.returned
  else
   s = past_sheet.draw - sheet.returned
  end



   if sheet.complete != true && sheet.store.vending_box == true
     sheet.update(complete: true)
       sheet.update(sold: s)
     
     short = (sheet.sold * 0.75) - sheet.collected  
     sheet.update(:shortage => short)
     
     pilferage = (sheet.shortage / 0.75)
     sheet.update(:pilferage => pilferage) 
   elsif sheet.complete != true && sheet.store.vending_box == false
     sheet.update(complete: true)
     sheet.update(sold: s)
     
     short = (sheet.sold * 0.55) - sheet.collected  
     sheet.update(:shortage => short)
     
     pilferage = (sheet.shortage / 0.55)
     sheet.update(:pilferage => pilferage)
   else

   end 
 end

 def before_update_calculations
  unless Sheet.find(self.id).complete == true
   Sheet.find(self.id).update(complete: false) 
  end
 end

def update_calculations
  store = Store.find(self.store_id)
  sheet = Sheet.find(self.id)
  past_sheet = store.sheets.find(self.id).previous

# will add back conditionals to deal with the .previous method, for when 
# it's the first record and as no previous item, such as in the create. 

   s = past_sheet.draw - sheet.returned

   if sheet.complete != true && sheet.store.vending_box == true
     sheet.update(complete: true)
     sheet.update(:sold => s)
     
     short = (sheet.sold * 0.75) - sheet.collected  
     sheet.update(:shortage => short)
     
     pilferage = (sheet.shortage / 0.75)
     sheet.update(:pilferage => pilferage) 


   elsif sheet.complete != true && sheet.store.vending_box == false 
     sheet.update(complete: true)
     sheet.update(:sold => s)

     short = (sheet.sold * 0.55) - sheet.collected  
     sheet.update(:shortage => short)
     
     pilferage = (sheet.shortage / 0.55)
     sheet.update(:pilferage => pilferage)
   else

   end 
end
         
end```

【问题讨论】:

标签: ruby-on-rails ruby


【解决方案1】:

您在after_update 中调用update,这将启动update 回调的新循环。

我宁愿使用我在回调上显式调用的方法,但如果您想坚持使用回调,请尝试在 before_update 回调中分配值,数据将更新一次。

【讨论】:

  • 谢谢@Uepsilon,这非常有帮助 - 它有助于回答。
【解决方案2】:

避免回调无限更新循环的好方法是使用仅用于该目的的变量。这个变量应该作为一个标志。启动时,运行回调。否则,跳过它。

因此,对于您的示例,您可以执行以下操作:

attr_accessor :this_is_the_flag

after_update update_calculations, :if => "this_is_the_flag.nil?"


def update_calculations
    [...]
    self.this_is_the_flag = true # invalidate the callback
end

这是大体思路,您可以根据需要进行调整。另外,请确保语法正确,因为回调语法往往会定期更改。

【讨论】:

  • 非常感谢@Ruby Racer - 工作就像一个魅力!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多