Null Object
What?
Replace conditional checks for nil
with an object that returns default data or nil
.
Why?
To tidy up conditional logic in our code.
Imagine you're building a message board. Messages are posted by registered users, but if a user should delete their account, the message is preserved and displayed without any identifying information.
Our view code may be scattered with helper methods like the following:
def author_username(post)
if post.author.present?
post.author.username
else
'Deleted user'
end
end
The more attributes of the user that we're displaying in the page, the more conditional statements we have checking for the existence of said user.
How?
How might we describe a user that no longer exists? We would like them to return some sensible data about what such a user might be, and if we ask them anything else that we might ask of an existing user, we at least want the system to not crash.
class NullUser
def username
'Deleted user'
end
def method_missing(*)
nil
end
end
And what if our instances of Post
had an author, even when they didn't?
class Post
def author
self[:author] || NullUser.new
end
end
Now the logic towards our view level becomes considerably more simple.
def author_username(post)
post.author.username
end
In fact, our helper method is now so simple that there is a strong argument for removing it entirely and calling our username method directly from the view.
<div class="post">
<span class="author"><%= @post.author.username %></span>
</div>