Module: Handshake::ClauseMethods
- Defined in:
- lib/handshake/handshake.rb
Overview
A collection of methods for defining constraints on method arguments.
Instance Method Summary collapse
-
#all?(*clauses) ⇒ Boolean
(also: #and?)
Passes only if all of the subclauses pass on the argument.
-
#any?(*clauses) ⇒ Boolean
(also: #or?)
Passes if any of the subclauses pass on the argument.
-
#anything ⇒ Object
Always passes.
-
#boolean? ⇒ Boolean
Passes if argument is true or false.
-
#clause(mesg = nil, &block) ⇒ Object
Passes if the given block returns true when passed the argument.
-
#hash_contract(hash) ⇒ Object
Passes if: * argument is a hash, and * argument contains only the keys explicitly specified in the given hash, and * every value contract in the given hash passes every applicable value in the argument hash E.g.
-
#hash_of?(key_clause, value_clause) ⇒ Boolean
Passes if argument is a Hash and if the key and value clauses pass all of its keys and values, respectively.
-
#hash_with_keys(*keys) ⇒ Object
(also: #hash_with_options)
Passes only if argument is a hash and does not contain any keys except those given.
-
#is?(class_symbol) ⇒ Boolean
Allows you to check whether the argument is_a? of the given symbol.
-
#many?(clause) ⇒ Boolean
Passes if argument is Enumerable and the subclause passes on all of its objects.
-
#many_with_map?(clause, mesg = nil, &block) ⇒ Boolean
Passes if argument is Enumerable and the subclause passes on all of its objects, mapped over the given block.
-
#nonzero? ⇒ Boolean
Passes if argument is numeric and nonzero.
-
#not?(clause) ⇒ Boolean
Passes if the subclause does not pass on the argument.
-
#responds_to?(*methods) ⇒ Boolean
Passes if argument responds to all of the given methods.
Instance Method Details
#all?(*clauses) ⇒ Boolean Also known as: and?
Passes only if all of the subclauses pass on the argument.
contract all?(Integer, nonzero?)
615 616 617 |
# File 'lib/handshake/handshake.rb', line 615 def all?(*clauses) clause("all of #{clauses.inspect}") { |o| clauses.all? {|c| c === o} } end |
#any?(*clauses) ⇒ Boolean Also known as: or?
Passes if any of the subclauses pass on the argument.
contract any?(String, Symbol) => anything
608 609 610 |
# File 'lib/handshake/handshake.rb', line 608 def any?(*clauses) clause("any of #{clauses.inspect}") { |o| clauses.any? {|c| c === o} } end |
#anything ⇒ Object
Always passes.
592 593 594 |
# File 'lib/handshake/handshake.rb', line 592 def anything Clause.new("anything") { true } end |
#boolean? ⇒ Boolean
Passes if argument is true or false.
contract self => boolean?
def ==(other)
...
end
601 602 603 604 |
# File 'lib/handshake/handshake.rb', line 601 def boolean? #clause("true or false") { |o| ( o == true ) || ( o == false ) } any?(TrueClass, FalseClass) end |
#clause(mesg = nil, &block) ⇒ Object
Passes if the given block returns true when passed the argument.
582 583 584 |
# File 'lib/handshake/handshake.rb', line 582 def clause(mesg=nil, &block) # :yields: argument Clause.new(mesg, &block) end |
#hash_contract(hash) ⇒ Object
Passes if:
-
argument is a hash, and
-
argument contains only the keys explicitly specified in the given hash, and
-
every value contract in the given hash passes every applicable value in the argument hash
E.g. hash_contract(:foo => String, :bar => Integer)
:foo => "foo" # passes
:bar => 3 # passes
:foo => "bar", :bar => 42 # passes
:foo => 88, :bar => "none" # fails
686 687 688 689 690 691 692 693 |
# File 'lib/handshake/handshake.rb', line 686 def hash_contract(hash) value_assertions = hash.keys.map do |k| clause("key #{k} requires #{hash[k].inspect}") do |o| o.has_key?(k) ? hash[k] === o[k] : true end end all? hash_with_keys(*hash.keys), *value_assertions end |
#hash_of?(key_clause, value_clause) ⇒ Boolean
Passes if argument is a Hash and if the key and value clauses pass all of its keys and values, respectively. E.g. hash_of?(Symbol, String)
:
:foo => "bar", :baz => "qux" # passes
:foo => "bar", "baz" => 3 # fails
653 654 655 656 657 |
# File 'lib/handshake/handshake.rb', line 653 def hash_of?(key_clause, value_clause) all_keys = many_with_map?(key_clause, "all keys") { |kv| kv[0] } all_values = many_with_map?(value_clause, "all values") { |kv| kv[1] } all? Hash, all_keys, all_values end |
#hash_with_keys(*keys) ⇒ Object Also known as: hash_with_options
Passes only if argument is a hash and does not contain any keys except those given. E.g. hash_with_keys(:foo, :bar, :baz)
:
:foo => 3 # passes
:foo => 10, :bar => "foo" # passes
:foo => "eight", :chunky_bacon => "delicious" # fails
666 667 668 669 670 671 |
# File 'lib/handshake/handshake.rb', line 666 def hash_with_keys(*keys) key_assertion = clause("contains keys #{keys.inspect}") do |o| ( o.keys - keys ).empty? end all? Hash, key_assertion end |
#is?(class_symbol) ⇒ Boolean
Allows you to check whether the argument is_a? of the given symbol. For example, is?(:String). Useful for situations where you want to check for a class type that hasn’t been defined yet when Ruby evaluates the contract but will have been by the time the code runs. Note that String => anything
is equivalent to is?(:String) => anything
.
709 710 711 712 713 |
# File 'lib/handshake/handshake.rb', line 709 def is?(class_symbol) clause(class_symbol.to_s) { |o| Object.const_defined?(class_symbol) && o.is_a?(Object.const_get(class_symbol)) } end |
#many?(clause) ⇒ Boolean
Passes if argument is Enumerable and the subclause passes on all of its objects.
class StringArray < Array
include Handshake
contract :+, many?(String) => self
end
632 633 634 |
# File 'lib/handshake/handshake.rb', line 632 def many?(clause) many_with_map?(clause) { |o| o } end |
#many_with_map?(clause, mesg = nil, &block) ⇒ Boolean
Passes if argument is Enumerable and the subclause passes on all of its objects, mapped over the given block.
contract many_with_map?(nonzero?, "person age") { |person| person.age } => anything
639 640 641 642 643 644 645 |
# File 'lib/handshake/handshake.rb', line 639 def many_with_map?(clause, mesg=nil, &block) # :yields: argument map_mesg = ( mesg.nil? ? "" : " after map #{mesg}" ) many_with_map = clause("many of #{clause.inspect}#{map_mesg}") do |o| o.map(&block).all? { |p| clause === p } end all? Enumerable, many_with_map end |
#nonzero? ⇒ Boolean
Passes if argument is numeric and nonzero.
621 622 623 |
# File 'lib/handshake/handshake.rb', line 621 def nonzero? all? Numeric, clause("nonzero") {|o| o != 0} end |
#not?(clause) ⇒ Boolean
Passes if the subclause does not pass on the argument.
587 588 589 |
# File 'lib/handshake/handshake.rb', line 587 def not?(clause) clause("not #{clause.inspect}") { |o| not ( clause === o ) } end |
#responds_to?(*methods) ⇒ Boolean
Passes if argument responds to all of the given methods.
696 697 698 699 700 701 |
# File 'lib/handshake/handshake.rb', line 696 def responds_to?(*methods) respond_assertions = methods.map do |m| clause("responds to #{m}") { |o| o.respond_to? m } end all? *respond_assertions end |