codenamev
5/20/2013 - 4:23 PM

A null object in Ruby with refinements

A null object in Ruby with refinements

module NullObject
  refine NilClass do
    def method_missing(method, *args, &block)
      self
    end

    def respond_to_missing?(*args)
      true
    end

    def tap; self; end
  end
end



# Ruby's nil now behaves like a Null Object, returning itself whenever a method
# is called. This means you don't have to check for presence anymore. No more
# `... unless value.nil?`! Dont worry, refinements are only valid on a per file
# basis. Your dependencies won't break, but the values they output in this file
# will be refined.

using NullObject

class Person
  def fetch
    @first_name = "john"
    @last_name  = "doe"
  end

  def first_name
    @first_name.capitalize
  end

  def last_name
    @last_name.capitalize
  end
end

person = Person.new
p person.first_name # => nil
p person.last_name  # => nil

person.fetch

p person.first_name # => "John"
p person.last_name  # => "Doe"



# The tests are written for cutest (https://github.com/djanowski/cutest). They
# can be run as follows: `cutest nullobject.rb`. Dont forget to `gem install 
# cutest`!

prepare { $test = 0 }
setup { nil }

test "should be falsey" do |x|
  assert (not x)
end

test "should return nil when calling a method" do |x|
  assert x.some_method.nil?
end

test "should return nil when #tapped" do |x|
  x.tap { $test = 1 }
  assert_equal $test, 0
end

test "should work on nil's returned from other libraries" do |x|
  require_relative "dependency"
  assert_equal Dependency.give_me_the_nil.some_method, x
end
module Dependency
  def self.give_me_the_nil
    nil
  end
end