2013-02-27 79 views
3

尽管在这里查看了一些关于rails中的空对象的答案,但我似乎无法让它们工作。Rails中关联的空对象模式

class User < ActiveRecord::Base 
    has_one :profile 
    accepts_nested_attributes_for :profile 

    def profile 
    self.profile || NullProfile #I have also tried 
    @profile || NullProfile #but it didn't work either 
    end 
end 

class NullProfile 
    def display #this method exists on the real Profile class 
    "" 
    end 
end 

class UsersController < ApplicationController 
    def create 
    User.new(params) 
    end 
end 

我的问题是,在用户创作,我通过在适当的嵌套属性(profile_attributes)的个人资料,我结束了我的新用户NullProfile。

我猜测这意味着我的自定义配置文件方法正在调用创建并返回一个NullProfile。我该如何正确执行这个NullObject,这样才会在读取时发生,而不是在初始创建对象时发生。

回答

3

我要精确地通过,我想要一个干净的新的对象,如果它是不存在的(如果你这样做只是让object.display不犯错,也许object.try(:display)越好)这也和这是我发现:

1:别名/ alias_method_chain

def profile_with_no_nill 
    profile_without_no_nill || NullProfile 
end 
alias_method_chain :profile, :no_nill 

但由于alias_method_chain已被弃用,如果你住在边上,你就必须自己手工做的模式... The answer here似乎提供更好的和更优雅的解决方案

2(简体/实际从答案的版本):

class User < ActiveRecord::Base 
    has_one :profile 
    accepts_nested_attributes_for :profile 

    module ProfileNullObject 
    def profile 
     super || NullProfile 
    end 
    end 
    include ProfileNullObject 
end 

注:你做这件事情(在链接的答案解释)


在你尝试过什么样的顺序:

当你做

def profile 
    @profile || NullProfile 
end 

因为协会延迟加载预期它不会表现(除非您在搜寻告诉它:include),这样@profile是零,这就是为什么你总是给我NullProfile

def profile 
    self.profile || NullProfile 
end 

它将失败,因为该方法被自称,所以它有点像一个递归方法,你会得到SystemStackError: stack level too deep

1

而不是使用alias_method_chain的,使用此:

def profile 
    self[:profile] || NullProfile.new 
end 
1

我发现不是在一个简单的选择包括接受答案中的私人模块。

您可以覆盖读取器方法并使用association方法从ActiveRecord中获取关联的对象。

class User < ApplicationRecord 
    has_one :profile 

    def profile 
    association(:profile).load_target || NullProfile 
    end 
end # class User