Как пропустить фильтр в модели с ruby ​​на рельсах 5.2? - PullRequest
0 голосов
/ 01 ноября 2018

Мое приложение управляет иерархией документов. Каждый документ имеет иерархический индекс, который рассчитывается только при создании. Файл document.rb начинается с

class BusinessRule < ActiveRecord::Base
### before filter
  before_create :set_hierarchy

и иерархия рассчитывается на основе родителя и братьев, так что self.hierarchy = last_one.next оценивается в области действия родителя.

Теперь я добавляю функцию управления версиями. Благодаря добавленному в контроллер методу new_version документ дублируется с помощью метода @document.dup, а затем сохраняется: предполагается, что иерархия остается неизменной, и необходимо увеличивать только номер версии.

Fine. Но фильтр before_create запускается действием сохранения в модели, и иерархия увеличивается, что не соответствует требованиям.

Как можно предотвратить срабатывание фильтра «до» в модели в случае действия new_version в контроллере?

Ответы [ 2 ]

0 голосов
/ 01 ноября 2018

Я думаю, что это хороший вариант для использования skip_callback метод:

BusinessRule.skip_callback(:create, :before, :set_hierarchy)

# your code to create BusinessRule objects without setting hierarchy
# ...

BusinessRule.set_callback(:create, :before, :set_hierarchy)

Если вы собираетесь пропускать / устанавливать обратные вызовы довольно часто, вы можете упростить это, используя специальный метод помощи:

# config/initializers/without_callback.rb

module ActiveSupport::Callbacks::ClassMethods
  def without_callback(*args, &block)
    skip_callback(*args)
    yield
    set_callback(*args)
  end
end

И вы сможете пропустить обратный вызов, как это:

BusinessRule.without_callback(:create, :before, :set_hierarchy) do 
  # your code to create BusinessRule objects without setting hierarchy
  # ...
end
0 голосов
/ 01 ноября 2018

Я не уверен, что это лучший способ сделать это, но я бы сделал что-то вроде этого.

class BusinessRule < ActiveRecord::Base
  attr_accessor :skip_set_hierarchy

  before_action :set_hierarchy, unless: :skip_set_hierarchy

  ...
end

Теперь, если вы не хотите, чтобы вызывался обратный вызов, вы можете установить для него значение true по требованию:

def new_version
  business_rule = BusinessRule.new business_rule_params
  business_rule.skip_set_hierarchy = true
  business_rule.save
  #this can be refactored a lot (set the skip_set_hierarchy to true inside params, use create instead of new, I made it verbose on purpose to make it clearer)
end

ActiveRecord пропустит обратный вызов, потому что skip_set_hierarchy вернет true. Вам не нужно изменять остальную часть кода, так как по умолчанию он вернет nil.

...