【问题标题】:How to skip_callback before_save for specific user?如何为特定用户跳过回调 before_save?
【发布时间】:2015-11-18 07:44:05
【问题描述】:

我的DailyOrdersController 中有一个名为update 的方法:

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

我现在要做的是,如果更新请求来自 current_admin,我希望跳过 refresh_total 回调。

我有 2 个使用 Devise gem 生成的用户模型:

  1. 用户(拥有current_user
  2. 管理员(有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

但如果更新请求来自current_admin(当登录用户是管理员用户时),它仍然无法正常工作并继续调用refresh_total 回调。

我现在该怎么办?

【问题讨论】:

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


    【解决方案1】:

    【讨论】:

      【解决方案2】:

      如果您跳过回调,您应该稍后启用它。无论如何,这看起来并不是最好的解决方案。也许你可以避免回调。

      一种方法是使用 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 对象,或者当至少一个属性被标记为只读时。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-10-22
        • 1970-01-01
        • 1970-01-01
        • 2010-11-23
        • 1970-01-01
        相关资源
        最近更新 更多