我有一个用户类,我试图附加工厂创建的配置文件。这是班级:
class User < ActiveRecord::Base
acts_as_authentic
has_one :profile
after_create {self.profile = ProfileFactory.create_profile(self.role)}
end
,工厂看起来像这样
class ProfileFactory
def self.create_profile(role)
String s = "#{role}#{"Profile"}"
Object.const_get(s).new
end
end
出于某种原因,它不会将自己视为用户。这是我在进行ProfileFactory.create_profile调用时遇到的错误
未定义的方法'角色'
#<Class:0x2304218>
用户对象有一个角色:在迁移过程中声明的字符串。
感谢任何帮助。
答案 0 :(得分:6)
Duncan在使用你的工厂作为回调方面得到了正确的答案。但它可以帮助你理解出了什么问题。
类方法接收类为self,实例方法接收实例为self。当您为块提供任何方法时,调用方法的范围将用于块。
after_create是一个类方法,它将回调添加回所提供的块或作为参数列出的方法。提供给回调的块(after_create,before_save等)在类方法的上下文中解释。因此,self不会引用正在创建的对象,而是引用正在创建的对象的类。
在此片段中:
after_create {self.profile = ProfileFactory.create_profile(self.role)}
self是User类,而不是您期望的User类的实例。
与Matt暗示的更传统的after_create语法相比,实例方法被添加到回调链中。在这种情况下,self指的是实例。
class User < ActiveRecord::Base
has_one :profile
after_create :add_profile
protected
def add_profile
self.profile = ProfileFactory.create_profile(role)
end
end
EmFi,这很有道理。所以 只是为了澄清,在调用方法时 这是班上的 回调方法但实际上并非如此 其中一个回调方法,允许我们 绕过这个类方法 问题,并使用当前实例?
是的,但不是出于您的想法。回调仅在传递符号时查找实例方法。
相反,你找到了解决实例方法问题的方法。你不能给回调一个类方法,但你可以为它提供一个调用它的块。我猜你也可以定义一个调用类方法的实例方法,但这看起来有些倒退。
答案 1 :(得分:1)
为什么不做一些更简单的事情?类似的东西:
class User < ActiveRecord::Base
has_one :profile
after_create :add_profile
protected
def add_profile
self.create_profile(:role => self.role)
end
end
class Profile < ActiveRecord::Base
belongs_to :user
end
您是否来自Java背景?
答案 2 :(得分:1)
有问题的User
对象作为参数传递给after_create
块。
class User < ActiveRecord::Base
after_create do |user|
user.profile = ProfileFactory.create_profile(user.role)
user.save
end
end