我有这样的事情:
class User < ActiveRecord::Base
has_one :profile
end
class Profile < ActiveRecord::Base
belongs_to :user
end
user = User.new
user.profile.something #=> ERROR
在这种情况下,设置默认配置文件对象的正确方法是什么?我试过这个:
class User < ActiveRecord::Base
default_scope :include => :profile
has_one :profile
def after_initialize
self.profile ||= Profile.new(:user => self)
end
end
...但是会产生N + 1个查询。有什么想法吗?
更新
这就是我现在拥有的,工作正常,仍在寻找更好的东西:
class User < ActiveRecord::Base
default_scope :include => :profile
has_one :profile, :autosave => true
def after_initialize
self.profile = Profile.new(:user => self) if new_record?
end
end
这样,只要您最终create
您的用户,您就会拥有个人资料。否则,唯一的情况是new_record?
。
答案 0 :(得分:3)
如果不存在,您可以编写自己的User#个人资料,为您构建一个:
class User < ActiveRecord::Base
has_one :profile
def profile_with_default
profile_without_default || build_profile
end
alias_method_chain :profile, :default
end
答案 1 :(得分:1)
我认为你的答案很好。我的解决方案略有不同:
class User < ActiveRecord::Base
default_scope :include => :profile
has_one :profile
alias_method :my_profile, :profile
def my_profile
self.profile = Profile.create(:user => self) unless self.profile
self.profile
end
end
不可强>
不太好
my_profile
(或者你想称之为)unless self.profile
检查答案 2 :(得分:0)
正确的答案取决于你的意图,因为没有直接解决这类问题。
在实例化对象之后调用after_initialize回调,因此对于这种逻辑来说它并不是一个好地方。
也许您应该尝试使用before_create / after_create代替?这些回调仅在对象创建时调用。
另外,不要使用Profile.new,而是使用以下方法之一:
self.build_profile(...)
self.create_profile(...)
在第二种情况下,模型正在保存。您可以将带有模型属性的哈希传递给两个方法(不要传递:user,因为它是自动设置的。)
答案 3 :(得分:0)
This是一个很好的答案:
class User < ActiveRecord::Base
has_one :preference_set
def preference_set
super || build_preference_set
end
end