Skip to content

Instantly share code, notes, and snippets.

@christhekeele
Last active August 29, 2015 13:57
Show Gist options
  • Save christhekeele/9571559 to your computer and use it in GitHub Desktop.
Save christhekeele/9571559 to your computer and use it in GitHub Desktop.
Method contracts for Ruby. No more `if object.respond_to? :waddle and object.respond_to? :quack and object.respond_to?...`
Gem::Specification.new do |s|
s.name = 'quack'
s.summary = ''
s.description = ''
s.version = '0.0.1'
s.platform = Gem::Platform::RUBY
s.files = ['quack.rb']
s.require_path = '.'
s.author = 'Chris Keele'
s.email = 'dev@chriskeele.com'
s.homepage = ''
s.test_file = 'quack_test.rb'
end
class Duck < BasicObject
attr_reader :requirements
def initialize(*args)
@requirements = args
end
def === other
requirements.all? do |requirement|
other.respond_to? requirement
end
end
end
class Object
def quacks_like?(contract)
contract === if self.respond_to? :const_defined? and self.const_defined? :Duck
self::Duck
else
self
end
end
end
require 'minitest/autorun'
class QuackTest < MiniTest::Unit::TestCase
Hash::Duck = Duck.new(:[], :[]=, :key?, :keys, :values)
class Hash::Sub < Hash; end
class Hash::Like
def [](_); end
def []=(_); end
def key?(_); end
def keys; end
def values; end
end
def test_hash
assert {}.quacks_like? Hash
assert {}.quacks_like? Hash.new
end
def test_hash_subclass
assert Hash::Sub.new.quacks_like? Hash
assert Hash::Sub.new.quacks_like? Hash.new
end
def test_hash_like
assert Hash::Like.new.quacks_like? Hash
assert Hash::Like.new.quacks_like? Hash.new
end
def test_unlike_hash
refute Array.new.quacks_like? Hash
refute Array.new.quacks_like? Hash.new
end
def test_duckless_fallback
assert Array.new.quacks_like? Array
assert [1,2,3].quacks_like? [1,2,3]
refute Hash.new.quacks_like? Array
refute [1,2,3].quacks_like? [1,2]
end
def test_hash_case
assert case {}
when Hash::Duck
true
end
refute case []
when Hash::Duck
true
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment