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
?
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
If you want to be able to chain methods on your NullUser
instance, you need to have method_missing
return self
instead of nil
. You attempt with returning self.class.new
was close ...
Avdi Grim explains how to implement a Null Object pattern in Ruby.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With