Skip to content

Instantly share code, notes, and snippets.

@britishtea
Last active March 30, 2017 19:43
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save britishtea/5613373 to your computer and use it in GitHub Desktop.
Save britishtea/5613373 to your computer and use it in GitHub Desktop.
A null object in Ruby with refinements
module Dependency
def self.give_me_the_nil
nil
end
end
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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment