Зарегистрируйте несколько условных обратных вызовов before_save в Rails 4

У меня есть два разных расчета для моей модели для двух разных полей. Перед сохранением.

Class Event < ActiveRecord::Base
  #some relations
  before_save :method1, unless: :some_field_1?
  before_save :method2, unless: :some_field_2?

  def method1
    some_field_1 = some_other_field / 2
  end

  def method2
    some_field_2 = some_field_1 / 3
  end
end

Проблема, с которой я сталкиваюсь, заключается в том, что some_field_1 имеет значение null при вызове метода2. Я предполагаю, что объявление обратных вызовов before_save, как это делаю я, неправильно.

  • Второе значение before_save перекрывает первое?
  • Выполняются ли обратные вызовы в том же порядке, в котором они объявлены?

Я знаю, что могу объединить два метода в один без условных выражений и решения проблем, но я бы предпочел иметь условные обратные вызовы. И я хочу знать, как правильно это сделать. Документы не очень ясно об этом.

Большое спасибо!

ИЗМЕНИТЬ

Для дальнейшего использования. Код был в порядке. Проблема была где-то еще (в БД)!


person limoragni    schedule 20.03.2015    source источник
comment
Я был бы очень недоволен, если бы полагался на порядок, в котором определены обратные вызовы, чтобы сделать это. Безусловно, надежнее вытолкнуть их обоих одним методом.   -  person David Aldridge    schedule 20.03.2015


Ответы (2)


Второе значение before_save перекрывает первое?

No

Выполняются ли обратные вызовы в том же порядке, в котором они объявлены?

да

Поскольку ваш атрибут не является логическим, вам, вероятно, не следует использовать вопросительный знак. Пытаться:

before_save :method1, unless: :some_field_1
before_save :method2, unless: :some_field_2
person RPinel    schedule 20.03.2015
comment
Кажется, у меня была другая проблема, и я предположил, что это из-за того, как я объявлял обратные вызовы. Но я решил другую проблему, и код работает! Так что этот ответ правильный. Знак вопроса был на своем месте, потому что на самом деле поле является целым числом. - person limoragni; 20.03.2015
comment
@limoragni Извините, я имел в виду не логическое значение. - person RPinel; 20.03.2015
comment
Ах хорошо! Тогда вы правы. Хотя сейчас код работает. Я собираюсь взглянуть на синтаксис вопросительного знака, возможно, я запутался в правильном его использовании. - person limoragni; 20.03.2015
comment
Если вы хотите, чтобы он был более явным, вы можете использовать синтаксис unless: "some_field_1.nil?" или if: "some_field_1.present?". - person RPinel; 20.03.2015
comment
Мне нравятся те! Исходя из фона Python, я всегда предпочитаю явное неявному! - person limoragni; 20.03.2015

Вы можете вызвать оба из них на одном и том же фильтре, разделенном запятой.

Ex.:

before_validation :t1, :t2

def t1; puts "t1"; end    
def t2; puts "t2"; end

Кажется, выполняется в этом порядке, в моих тестах.

Кроме того, из документации (http://api.rubyonrails.org/classes/ActiveRecord/Callbacks.html):

Отмена обратных вызовов

Если обратный вызов before_* возвращает false, все последующие обратные вызовы и связанное с ними действие отменяются. Если обратный вызов after_* возвращает false, все последующие обратные вызовы отменяются. Обратные вызовы обычно выполняются в том порядке, в котором они определены, за исключением обратных вызовов, определенных как методы модели, которые вызываются последними.

Если вы хотите, чтобы что-то было сделано до before_save, вы можете установить один из фильтров, которые срабатывают перед ним, например, after_validation, для выполнения этих заданий.

person Thyago B. Rodrigues    schedule 20.03.2015
comment
Да, это правильно. Но в этом случае я бы не знал, как использовать условное выражение before_save :method1, если только: :some_field_1? что я и пытаюсь сохранить! Спасибо! - person limoragni; 20.03.2015
comment
Добавил еще кое-что в свой ответ. Это приемлемый вариант для вас? - person Thyago B. Rodrigues; 20.03.2015
comment
Это полезная информация, но у меня нет проблем с отменой обратных вызовов, и я хочу вызывать методы before_save. Спасибо, но в итоге код был Ок, проблема была в другом. Иногда, когда вы описываете проблему, всплывает решение! Спасибо за ответ, но я отметил ответ Роке Пинеля как правильный, потому что он отвечает на два основных вопроса, которые я задал! - person limoragni; 20.03.2015