Я пытаюсь установить некоторые значения по умолчанию для объекта, используя 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 с блоком и без, или значения по умолчанию блокируются блоком?
ОБНОВЛЕНИЕ
Обнаружена проблема.
Оказывается, что вызов 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
.Не самый чистый, но это решило проблему.
Спасибо Брэндону за то, что он указал мне правильное направление.