Rails:如果没有找到,则创建关联以避免 nil 错误 [英] Rails: Create association if none is found to avoid nil errors

查看:18
本文介绍了Rails:如果没有找到,则创建关联以避免 nil 错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个应用程序,我的用户可以在其中设置一组首选项.两者都存储为 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆