Rails: replacing try with the Null Object Pattern
design-patterns, ruby, ruby-on-rails
Solution
I would stick with the `NullUser` but change its name to `GuestUser` to make things clearer. Additionally you should stub all important method from your User class, e.g.
class GuestUser
def method_missing(method_name, *args)
nil
end
def is_admin?
false
end
# maybe even fields:
def name
"Guest"
end
# ...
end
Problem
In most of my applications, I have a `current_user` method. To avoid exceptions in cases like `current_user.name` where `current_user` is `nil`, rails provides the `try` method. The problem with this is that I need to remember to use `try` wherever `current_user` might be `nil`. I want to use the Null Object pattern to remove this additional overhead. ``` 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 ``` This can replace `try` in some cases: ``` current_user.try(:first_name) #=> nil current_user.first_name #=> nil ``` but fails with further chaining: ``` current_user.profiles.first.name #=> undefined method... ``` I tried to return the null object: ``` 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 ``` but this would fail in other cases: ``` current_user.is_admin? #=> #<NullUser:0x96f4e98> ``` Is there a possible solution to this problem or do we all have to live with `try`?