From time to time most of the Ruby/Rails developers are facing a situation when an app is trying to call a method on a certain object, which out of nowhere appears in our system as
nil, instead of an instance of the desired class. The worst scenario in such situations, assuming that you want to solve this problem somehow, is to take advantage of Ruby’s open classes and achieve a
quick win by monkey-patching the
NilClass to avoid raising the famous
NoMethodError. Even if you’re new in Ruby world, you should know that it’s a really bad practice and do not do that. You can, of course, achieve the goal in a few different ways, and here we’ll be describing one of them. Have you ever heard about the NullObject pattern? Here’s a quick introduction on how to use it.
I think the most popular version of this problem is when you have a regular
User class with some roles and sessions handling. In some situations, you have to perform a double checking when you want to check if your user is logged in as admin. Given that your app is operating on logged in users a helper method like
current_user, you can’t just check if e.g.
current_user.is_admin? is true. Why? Because if there is no
current_user you’ll get an error
That’s why you have to check two things:
current_user && current_user.is_admin?. I bet you can imagine much more examples when you’re somehow checking if an object is nil. Very often the best solution to implement is the NullObject pattern.
Following the example above, let’s create a
GuestUser class*, which implements our
is_admin? method, that returns false, of course.
1 2 3 4 5
Now we have to find the place where our
current_user is defined and make a simple condition to return the real user or the
GuestUser when needed. For example:
1 2 3 4 5 6 7
And that’s it! You can call
current_user.is_admin? without double checking if the user is currently logged in. So clean!
Every attempt to directly monkey-patch any core Ruby class (including NilClass), instead of providing an explicit solution of the problem, may lead to more unexpected side effects than benefits. That’s why it’s worth to know the patterns. Patterns help you to keep your code clean and maintainable. Of course - there’s no silver bullet for any code and you should use the patterns you know wisely. And in proper places.
* - We should call it
NullUser, but how ridiculously does it sound?!