Я пытаюсь установить некоторые значения по умолчанию для объекта с помощью after_initialize
. Проблема, с которой я сталкиваюсь, заключается в том, что я бы хотел, чтобы это вызывалось независимо от того, как создается объект.
Мой класс:
class Foo < ActiveRecord::Base
serialize :data
after_initialize :init
def init
self.data ||= {}
self.bar ||= "bar"
self.baz ||= "baz"
end
end
Все работает нормально, если я вызываю Foo.new
, Foo.new(:bar => "things")
и Foo.create(:baz => 'stuff')
. Однако, когда я использую блок с create
, обратный вызов after_initialize
не запускается.
obj = Foo.create do |f|
f.bar = "words"
f.data = { :attr_1 => 1, :attr_2 => 2 }
end
Это просто возвращает obj.baz
= > nil
вместо "baz"
, если другие атрибуты установлены правильно.
Я пропустил что-то с тем, как выполняются обратные вызовы, с различиями с вызовом create с блоком и без или по умолчанию значения, сбитые блоком?
UPDATE
Обнаружена проблема.
Оказывается, что вызов create
с блоком и без, является немного отличающимся. Когда вы вызываете create
без блока и просто передаете хэш параметров, для всех целей и задач вы вызываете Foo.new({<hash of argument>}).save
, а обратный вызов after_initialize
запускается непосредственно перед сохранением, как вы ожидали.
Когда вы вызываете create
с блоком, происходит что-то немного другое. Порядок событий Foo.new
вызывается с любыми аргументами, которые вы передаете, затем вызывается after_initialize
, затем блок запускается. Поэтому, если вы используете блок (как я был) взаимозаменяемо с параметрами хэша, чтобы сделать вещи немного более удобочитаемыми, вы можете получить бит, потому что ваш after_initialize
запускается до того, как все параметры, которые вы намереваетесь установить, действительно установлены.
Я получил бит, потому что я делал дополнительную работу в after_initialize
, чтобы установить дополнительные атрибуты, основанные на значении того, что передавалось. Поскольку ничего не было установлено при вызове after_initialize
, ничего не установлено правильно, и мои проверки не удались.
Мне пришлось сделать вызовы init
. Один раз на after_initialize
и один раз на before_validation
. Не самый чистый, но он решил проблему.
Спасибо, Брэндон за то, что указал мне в правильном направлении.