Last active
March 30, 2017 19:43
-
-
Save britishtea/5613373 to your computer and use it in GitHub Desktop.
A null object in Ruby with refinements
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module Dependency | |
def self.give_me_the_nil | |
nil | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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