Module: Kernel
- Defined in:
- lib/contract/integration.rb
Instance Method Summary collapse
-
#adaption(options = {}, &block) ⇒ Object
Adds an adaption route from the specified type to the specified type.
Instance Method Details
#adaption(options = {}, &block) ⇒ Object
Adds an adaption route from the specified type to the specified type. Basic usage looks like this:
adaption :from => StringIO, :to => String, :via => :read
This method takes various options. Here's a complete list:
:from::
The type that can be converted from. Defaults to +self+ meaning you
can safely omit it in Class, Module or Contract context.
:to::
The type that can be converted to. Defaults to +self+ meaning you
can safely omit it in Class, Module or Contract context.
Note that you need to specify either <code>:from</code> or
<code>:to</code>.
:via::
How the <code>:from</code> type will be converted to the
<code>:to</code> type. If this is a Symbol the conversion will be
done by invoking the method identified by that Symbol on the
source object. Otherwise this should be something that responds to
the +call+ method (for example Methods and Procs) which will get
the source object as its argument and which should return the
target object.
:if::
The conversion can only be performed if this condition is met.
This can either be something that implements the === case
equivalence operator or something that implements the +call+
method. So Methods, Procs, Modules, Classes and Contracts all
make sense in this context. You can also specify a Symbol in
which case the conversion can only be performed if the source
object responds to the method identified by that Symbol.
Note that the <code>:if</code> option will default to the same
value as the <code>:via</code> option if the <code>:via</code>
option is a Symbol.
If you invoke this method with a block it will be used instead of
the :via option.
See Contract.adapt for how conversion look-ups are performed.
512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 |
# File 'lib/contract/integration.rb', line 512 def adaption( = {}, &block) # :yield: source_object = { :from => self, :to => self }.merge() if block then if .include?(:via) then raise(ArgumentError, "Can't use both block and :via") else [:via] = block end end if [:via].respond_to?(:to_sym) then [:via] = [:via].to_sym end [:if] ||= [:via] if [:via].is_a?(Symbol) if [:via].is_a?(Symbol) then symbol = [:via] [:via] = lambda { |obj| obj.send(symbol) } end if [:if].respond_to?(:to_sym) then [:if] = [:if].to_sym end if [:if].is_a?(Symbol) then [:if] = Contract::Check::Quack[[:if]] elsif [:if].respond_to?(:call) then callable = [:if] [:if] = Contract::Check.block { |obj| callable.call(obj) } end if [:from] == self and [:to] == self then raise(ArgumentError, "Need to specify either :from or :to") elsif [:from] == [:to] then raise(ArgumentError, "Self-adaption: :from and :to both are " + [:to].inspect) end unless [:via] raise(ArgumentError, "Need to specify how to adapt (use :via or block)") end Contract.adaptions[[:to]] << end |