One of our teammates will get back to you soon.
Null Object pattern can reduce you some code complexity and it's pretty simple to use.
A design is far better when there are no exceptions. Whenever you write an if statement, Nyan Cat cries.
Yesterday I remembered this blog quote when I faced a common situation handling nested hashes in Ruby.
hash = {
company_name: "Stack Builders",
address: {
line_1: "315 Fifth Avenue",
line_2: "Suite 703A",
city: "New York",
state: "NY",
},
}
What if I want to get some of that data and use it to manually instantiate a Company
entity? Wll, attributes for that entity are not nested like the hash is:
Company.new(
name: hash.fetch(:company_name),
address_line_1: hash.fetch(:address).fetch(:line_1),
address_line_2: hash.fetch(:address).fetch(:line_2),
city: hash.fetch(:address).fetch(:city),
state: hash.fetch(:address).fetch(:state)
)
That's not the most beautiful piece of code, but it works if--and only--if all keys are present. If not fetch
will complain. You can say, "But what if we use []
method instead of fetch
?" Well, if the address
key is missing in our hash
, the code hash[:address][:line_1]
will throw a NoMethodError for NilClass
. Not ideal.
What now? "Add an if
, it will fix that." Mmmm... yes, it will solve the problem, but do you remember the quote at the beginning of this post? I want to avoid adding if
statements to this piece of code. This is where the Null Object pattern enters.
I used a very simple implementation of this pattern just to satisfy cases like this one. We can use it in many different ways and have a lot of flexibility, I just wanted to avoid the NoMethodError
being thrown again.
# null_object.rb
class NullObject
def method_missing(*args, &block)
nil
end
end
# company.rb
address = hash.fetch(:address, NullObject.new)
Company.new(
name: hash.fetch(:company_name),
address_line_1: address.fetch(:line_1),
address_line_2: address.fetch(:line_2),
city: address.fetch(:city),
state: address.fetch(:state)
)
This way the NullObject
instance is just nullifying my call to fetch
, because I don't have that :address
key. This improved my design, simplified my code, and made it safer.
Why don't you go ahead give it a try? It might be as helpful for you as it was for me. Here I created my own implementation of this pattern, a very simple one, no fanciness needed, but if you want something more sophisticated check out Naughy, by Avdi Grimm.
Published on Nov. 21, 2014
Join our community of avid readers and stay informed with the latest articles, tips, and insights delivered straight to your inbox. Don't miss out on valuable content – subscribe now and be part of the conversation!
We care about your data. Check out our Privacy Policy.