2013-04-18 8 views
5

私のほとんどのアプリケーションでは、current_userメソッドがあります。 のような例外を回避するために、current_usernilの場合、レールはtryメソッドを提供します。これの問題は、current_usernilの可能性があるところでtryを使用することを覚えておく必要があることです。Rails:Nullオブジェクトパターンでtryを置き換える

この追加のオーバーヘッドを削除するには、Nullオブジェクトパターンを使用します。

current_user.try(:first_name)  #=> nil 
current_user.first_name   #=> nil 

が、さらなるチェーンで失敗します:

class NullUser 
    def method_missing(method_name, *args) 
    self.class.new 
    end 
end 

current_user.try { |u| u.profiles.first.name } #=> nil 
current_user.profiles.first.name    #=> nil 
:私はnullオブジェクトを返すようにしようとした

current_user.profiles.first.name #=> undefined method... 

これは、いくつかのケースでtryを置き換えることができます

class NullUser 
    def method_missing(method_name, *args) 
    nil 
    end 
end 

def current_user 
    return NullUser.new unless UserSession.find 
    @current_user ||= UserSession.find.user 
end 

が、これは他のケースでは失敗します:

current_user.is_admin?   #=> #<NullUser:0x96f4e98> 

は、この問題に対する可能な解決策はあるのか、我々はすべてのtryで生きているのですか?

+1

を理解することはできません。なぜそれは正しく分割されていないのですか? – apneadiving

答えて

7

私はNullUserを使用しますが、その名前をGuestUserに変更してより明確にします。さらに、すべての重要なメソッドをUserクラスからスタブする必要があります。

class GuestUser 
    def method_missing(method_name, *args) 
    nil 
    end 

    def is_admin? 
    false 
    end 

    # maybe even fields: 
    def name 
    "Guest" 
    end 

    # ... 
end 
2

あなたNullUserインスタンス上の連鎖メソッドにできるようにしたい場合は、代わりにnilmethod_missingリターンselfを持っている必要があります。あなたはログインしているユーザーと匿名ユーザーの間で同じページを共有するように見える、なぜあなたはself.class.newを返すことは近くにあったとしよう...

Avdi Grim explains how to implement a Null Object pattern in Ruby.