2013-02-27 74 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