Last active
August 29, 2015 13:57
-
-
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?...`
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
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 = '[email protected]' | |
s.homepage = '' | |
s.test_file = 'quack_test.rb' | |
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
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 |
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
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