0

У меня есть метод, названный update внутри моего DailyOrdersController:Как skip_callback before_save для конкретного пользователя?

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.

У меня есть 2 пользовательская модель генерируется с использованием DEViSE перл:

  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 

Но он не работает и продолжает звонить по телефону refresh_total, если запрос на обновление поступает от current_admin (когда пользователь вошел в систему пользователем admin).

Что мне теперь делать?

ответ

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

Даже лучше, вы можете позвонить update_columns. Вот что он говорит в documentation of the method:

обновления атрибутов непосредственно в базе данных, выдающие в UPDATE SQL заявление и устанавливает их в приемнике:

user.update_columns (last_request_at: Time.current)

Это самый быстрый способ обновления атрибутов, поскольку он напрямую связан с базой данных , но учтите, что в результате обычные обновления процедуры полностью обойдены. В частности:

  • \ Валидации пропускаются.
  • \ Обратные вызовы пропускаются.
  • + updated_at +/+ updated_on + не обновляется.

    Этот метод вызывает ActiveRecord :: ActiveRecordError при вызове в новых объектах или когда хотя бы один из атрибутов помечен как readonly.

Смежные вопросы