Rails:如果没有找到关联,则创建关联以避免零错误
我有一个应用程序,我的用户可以在其中拥有一组首选项。两者都存储为 ActiveRecord-models,如下所示:
class User < AR::Base
has_one :preference_set
end
class PreferenceSet < AR::Base
belongs_to :user
end
我现在可以访问用户的首选项:
@u = User.first
@u.preference_set => #<PreferenceSet...>
@u.preference_set.play_sounds => true
但是如果尚未创建首选项集,则会失败,因为 @u.preference_set 将返回 nil,并且我将调用 play_sounds
为 nil
。
我想要归档的是 User.preference_set 总是返回一个 PreferenceSet 实例。我尝试像这样定义它:
class User < ..
has_one :preference_set
def preference_set
preference_set || build_preference_set
end
end
这导致“堆栈级别太深”
,因为它递归地调用自身。
我的问题是:
如何确保 @user.preference_set
返回相应的preference_set-record,或者如果不存在,则构建一个新的?
我知道我可以重命名我的关联(例如 preference_set_real
)并通过这种方式避免递归调用,但为了我的应用程序的简单性,我想保留命名。
谢谢!
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
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
.
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
This is causing a 'Stack level too deep'
, since it is calling itself recursively.
My question is this:
How can I ensure that @user.preference_set
returns either the corresponding preference_set-record or, if none exists, builds a new one?
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.
Thanks!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
有一个优雅简单的形式:
ActiveRecord 有意启用这种
super
的使用来覆盖关联方法的行为。There's an elegantly simple form:
ActiveRecord intentionally enables such use of
super
to override the behaviour of association methods.那么,最好的方法是在创建主记录时创建关联记录:
这将对其进行设置,以便每当创建
User
时,PreferenceSet
也会创建。如果您需要使用参数初始化关联记录,请在before_create
中调用不同的方法,该方法调用build_preference_set(:my_options => "here")
然后返回 <代码> true。然后,您可以通过迭代任何没有
PreferenceSet
的记录并通过调用#create_preference_set
构建一个来标准化所有现有记录。如果您只想在绝对需要时创建
PreferenceSet
,那么您可以执行以下操作:Well the best way to do this is to create the associated record when you create the primary one:
That will set it up so whenever a
User
is created, so is aPreferenceSet
. If you need to initialise the the associated record with arguments, then call a different method inbefore_create
which callsbuild_preference_set(:my_options => "here")
and then returnstrue
.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
.If you want to only create the
PreferenceSet
when it is absolutely needed, then you can do something like: