【问题标题】:Rails: Create association if none is found to avoid nil errorsRails:如果没有找到则创建关联以避免零错误
【发布时间】:2010-09-28 12:29:52
【问题描述】:

我有一个应用程序,我的用户可以在其中拥有一组偏好。两者都存储为 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,并且我将在 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)并避免以这种方式进行递归调用,但为了我的应用程序简单起见,我想保留命名。

谢谢!

【问题讨论】:

    标签: ruby-on-rails activerecord has-one


    【解决方案1】:

    有一个优雅简单的形式:

    class User < ApplicationRecord
      has_one :preference_set
      
      def preference_set
        super || build_preference_set
      end
    end
    

    ActiveRecord intentionally enables 这样使用super 来覆盖关联方法的行为。

    【讨论】:

    • 这就是我要找的。​​span>
    【解决方案2】:

    最好的方法是在创建主记录时创建关联记录:

    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 =&gt; "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
    

    【讨论】:

    猜你喜欢
    • 2012-02-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-24
    • 2010-10-26
    • 1970-01-01
    • 2019-12-18
    • 2013-07-24
    • 1970-01-01
    相关资源
    最近更新 更多