Ruby on rails 3 使用块调用create时,初始化后的Rails 3未运行
我试图在初始化后使用Ruby on rails 3 使用块调用create时,初始化后的Rails 3未运行,ruby-on-rails-3,activerecord,Ruby On Rails 3,Activerecord,我试图在初始化后使用为对象设置一些默认值。我遇到的问题是,无论对象是如何创建的,我都希望调用它 我的班级: class Foo < ActiveRecord::Base serialize :data after_initialize :init def init self.data ||= {} self.bar ||= "bar" self.baz ||= "baz" end end 这只会生成obj.baz=>nil,而不是“baz”
为对象设置一些默认值。我遇到的问题是,无论对象是如何创建的,我都希望调用它
我的班级:
class Foo < ActiveRecord::Base
serialize :data
after_initialize :init
def init
self.data ||= {}
self.bar ||= "bar"
self.baz ||= "baz"
end
end
这只会生成obj.baz
=>nil
,而不是“baz”
,并正确设置其他属性
我是否在执行回调的方式上遗漏了一些东西,调用create时有块和无块的区别,或者默认值是否被块破坏了
更新
发现了问题
事实证明,使用block和不使用block调用create
有着微妙的区别。当您在没有块的情况下调用create
并只传入散列参数时,出于所有目的,您正在调用Foo.new({}).save
,并且在初始化之后的回调会像您预期的那样在保存之前执行
当您使用块调用create
时,会发生一些不同的情况。事件的顺序是Foo。使用传入的任何参数调用new
,然后在调用\u initialize
后调用,然后运行块。因此,如果您使用块(就像我一样)与散列参数互换,只是为了让事情更可读一点,那么您可能会得到位,因为您的在初始化之后运行,而您打算设置的所有参数实际上都设置好了
我被咬是因为我在初始化后在中做了一些额外的工作,根据传递的值设置了一些额外的必需属性。由于在调用_initialize
后时实际上没有设置任何内容,因此没有正确设置任何内容,我的验证失败
最后我不得不调用init
。初始化后一次启用,\u验证前一次启用。不是最干净的,但它解决了问题
感谢布兰登为我指出了正确的方向。我无法重现这一点。我碰巧手头有一个应用程序,可以使用以下(简化)类:
因此create
调用new
并将值分配给object
之前的yield
s。以下是新的中的相关部分:
def initialize(attributes = nil)
# truncated for space
result = yield self if block_given?
run_callbacks :initialize
result
end
如您所见,new
在返回之前无条件地调用initialize
回调,因此在create
之前,甚至在您传递的块屈服之前当块获取对象时,初始化后的方法已经执行了
仔细检查:(1)您的Rails版本是最新的(我相信现在是3.0.5),并且(2)如果您使用Foo.new
(即使用声明的块方法)执行相同的操作,则没有任何设置baz
。,同样的事情也会发生吗?Foo.new加一个block就可以了。@HMCFletch-很好地解释了发生了什么-谢谢你为这篇粗体文章分享了大量的经验。这正是造成我问题的原因。我在问题的底部写了一个小解释,详细说明发生了什么。谢谢你的帮助。很有趣,很好,你把事情搞清楚了。我无法想象你是唯一一个被咬过的人。。。
class Service < ActiveRecord::Base
serialize :data, Hash
after_initialize :create_default_data
attr_accessible :data, :token
protected
def create_default_data
self.data ||= Hash.new
end
end
ruby-1.9.2-p136 :001 > obj = Service.create do |s|
ruby-1.9.2-p136 :002 > s.token = "abc"
ruby-1.9.2-p136 :003?> end
=> #<Service id: 22, user_id: nil, type: nil, data: {}, created_at: "2011-03-05 04:18:00", updated_at: "2011-03-05 04:18:00", token: "abc">
ruby-1.9.2-p136 :004 > obj.data
=> {}
def create(attributes = nil, &block)
if attributes.is_a?(Array)
attributes.collect { |attr| create(attr, &block) }
else
object = new(attributes)
yield(object) if block_given?
object.save
object
end
end
def initialize(attributes = nil)
# truncated for space
result = yield self if block_given?
run_callbacks :initialize
result
end