Rails:如果找不到任何错误,则创建关联
我有一个应用程序,我的用户可以拥有一组首选项。 两者都存储为ActiveRecord模型,如下所示:
class User < AR::Base has_one :preference_set end class PreferenceSet < AR::Base belongs_to :user end
我现在可以访问用户的首选项:
@u = User.first @u.preference_set => # @u.preference_set.play_sounds => true
但是如果尚未创建首选项集,则会失败,因为@ u.preference_set将返回nil,并且我将在nil
上调用play_sounds
。
我想归档的是User.preference_set总是返回一个PreferenceSet实例。 我试过像这样定义它:
class User < .. has_one :preference_set def preference_set preference_set || build_preference_set end end
这导致'Stack level too deep'
,因为它以递归方式调用自身。
我的问题是:
如何确保@user.preference_set
返回相应的preference_set-record,如果不存在,则构建一个新的?
我知道我可以重命名我的关联(例如, preference_set_real
)并以这种方式避免递归调用,但为了简化我的应用程序,我想保留命名。
谢谢!
那么,最好的方法是在创建主要记录时创建关联记录:
class User < ActiveRecord::Base has_one :preference_set, :autosave => true before_create :build_preference_set end
这将设置它,以便每当创建User
, PreferenceSet
也是如此。 如果需要使用参数初始化关联记录,则在before_create
中调用build_preference_set(:my_options => "here")
调用build_preference_set(:my_options => "here")
,然后返回true
。
然后,您可以通过迭代任何没有PreferenceSet
并通过调用#create_preference_set
构建一个来对所有现有记录进行规范化。
如果您只想在绝对需要时创建PreferenceSet
,那么您可以执行以下操作:
class User < ActiveRecord::Base has_one :preference_set def preference_set_with_initialize preference_set_without_initialize || build_preference_set end alias_method_chain :preference_set, :initialize end
或简单地说
class User < ApplicationRecord has_one :preference_set def preference_set super || build_preference_set end end