我的update
中有一个名为DailyOrdersController
的方法:
def update
if @daily_order.update( daily_order_params.merge({default_order:false}) )
respond_or_redirect(@daily_order)
else
render :edit
end
end
我的DailyOrder
型号:
before_save :refresh_total
def refresh_total
# i do something here
end
我现在要做的是,如果更新请求来自refresh_total
,我希望跳过current_admin
回调。
我使用Devise gem生成了2个用户模型:
current_user
)current_admin
)我试着这样做:
def update
if current_admin
DailyOrder.skip_callback :update, :before, :refresh_total
end
if @daily_order.update( daily_order_params.merge({default_order:false}) )
respond_or_redirect(@daily_order)
else
render :edit
end
end
但是如果更新请求来自refresh_total
(当登录用户是管理员用户时),它仍无法正常工作并仍然继续调用current_admin
回调。
我现在该怎么办?
答案 0 :(得分:2)
答案 1 :(得分:0)
如果您跳过回调,则应在以后启用它。无论如何,这看起来不是最好的解决方案。也许你可以避免回调。
一种方法是使用update_all:
DailyOrder.where(id: @daily_order.id).update_all( daily_order_params.merge({default_order:false}) )
或者你可以这样做:
#in the model:
before_validation :refresh_total
#in the controller
@daily_order.assign_attributes( daily_order_params.merge({default_order:false}) )
@daily_order.save(validate: current_admin.nil?)
或者最好在模型中添加一个新列: refresh_needed 然后你会在before_validation上有条件地更新该列,而在before_save上你仍会调用相同的回调,但是有条件地到refresh_needed的状态。在此回调中,您应该重置该列。如果您希望我用一些代码来说明这一点,请告诉我。
这可能会派上用场: http://www.davidverhasselt.com/set-attributes-in-activerecord/
<强>更新强>
更好的是,您可以调用 update_columns 。 以下是documentation of the method中的内容:
直接在发出UPDATE SQL的数据库中更新属性 声明并将它们设置在接收器中:
user.update_columns(last_request_at:Time.current)
这是更新属性的最快方法,因为它直接进行 数据库,但考虑到因此定期更新 程序完全被绕过。特别是:
- \跳过验证。
- \跳过回调。
+ updated_at + / + updated_on +未更新。
当在new上调用时,此方法引发ActiveRecord :: ActiveRecordError 对象,或至少有一个属性被标记为只读时。