Rails: replacing try with a Null Object template

In most of my applications, I have a current_user method. To avoid exceptions in cases such as current_user.name , where current_user is nil , the rails provide a try method. The problem is that I need to remember to use try wherever current_user can be nil .

I want to use the Null Object pattern to remove this extra 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 

In some cases, this may replace try :

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

but with further closure it doesn’t work:

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

I tried to return a 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 will fail in other cases:

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

Is there a possible solution to this problem or should we all live with try ?

+5
source share
2 answers

I would stick with NullUser , but change its name to GuestUser to make everything more understandable. In addition, you must stub all important methods from your User class, for example

 class GuestUser def method_missing(method_name, *args) nil end def is_admin? false end # maybe even fields: def name "Guest" end # ... end 
+7
source

If you want to use chaining methods on your NullUser instance, you need method_missing to return self instead of nil . Are you trying to return self.class.new was close ...

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

+2
source

Source: https://habr.com/ru/post/956327/


All Articles