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