Rails:如果没有找到,则创建关联以避免 nil 错误 [英] Rails: Create association if none is found to avoid nil errors
问题描述
我有一个应用程序,我的用户可以在其中设置一组首选项.两者都存储为 ActiveRecord 模型,如下所示:
I have an application where my users can have a set of preferences. Both are stored as ActiveRecord-models as follows:
class User < AR::Base
has_one :preference_set
end
class PreferenceSet < AR::Base
belongs_to :user
end
我现在可以访问用户的首选项:
I can now access the preferences of a user:
@u = User.first
@u.preference_set => #<PreferenceSet...>
@u.preference_set.play_sounds => true
但如果尚未创建首选项集,则会失败,因为@u.preference_set 将返回 nil,而我将在 nil
上调用 play_sounds
.
But this fails if a preference set is not already created, since @u.preference_set will be returning nil, and I'll be calling play_sounds
on nil
.
我想要存档的是 User.preference_set 总是返回一个 PreferenceSet 实例.我试过这样定义它:
What I want to archive is that User.preference_set always returns a PreferenceSet instance. I've tried defining it like this:
class User < ..
has_one :preference_set
def preference_set
preference_set || build_preference_set
end
end
这会导致 'Stack level too deep'
,因为它递归地调用自己.
This is causing a 'Stack level too deep'
, since it is calling itself recursively.
我的问题是:
如何确保 @user.preference_set
返回相应的首选项集记录,或者如果不存在,则构建一个新记录?
How can I ensure that @user.preference_set
returns either the corresponding preference_set-record or, if none exists, builds a new one?
我知道我可以重命名我的关联(例如 preference_set_real
)并避免以这种方式进行递归调用,但为了我的应用程序的简单性,我想保留命名.
I know I could just rename my association (eg. preference_set_real
) and avoid recursive calls this way, but for the sake of simplicity in my app, I'd like to keep the naming.
谢谢!
推荐答案
最好的方法是在创建主要记录时创建关联记录:
Well the best way to do this is to create the associated record when you create the primary one:
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")
然后返回 <代码>真代码>.
That will set it up so whenever a User
is created, so is a PreferenceSet
. If you need to initialise the the associated record with arguments, then call a different method in before_create
which calls build_preference_set(:my_options => "here")
and then returns true
.
然后,您可以通过迭代任何没有 PreferenceSet
的记录并通过调用 #create_preference_set
构建一个来规范化所有现有记录.
You can then just normalise all existing records by iterating over any that don't have a PreferenceSet
and building one by calling #create_preference_set
.
如果您只想在绝对需要时创建 PreferenceSet
,那么您可以执行以下操作:
If you want to only create the PreferenceSet
when it is absolutely needed, then you can do something like:
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
这篇关于Rails:如果没有找到,则创建关联以避免 nil 错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!