Module | Kernel |
In: |
lib/contract/integration.rb
|
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 :from or :to. |
:via: | How the :from type will be converted to the :to 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 :if option will default to the same value as the :via option if the :via 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.
# File lib/contract/integration.rb, line 512 512: def adaption(options = {}, &block) # :yield: source_object 513: options = { 514: :from => self, 515: :to => self 516: }.merge(options) 517: 518: if block then 519: if options.include?(:via) then 520: raise(ArgumentError, "Can't use both block and :via") 521: else 522: options[:via] = block 523: end 524: end 525: 526: if options[:via].respond_to?(:to_sym) then 527: options[:via] = options[:via].to_sym 528: end 529: 530: options[:if] ||= options[:via] if options[:via].is_a?(Symbol) 531: 532: if options[:via].is_a?(Symbol) then 533: symbol = options[:via] 534: options[:via] = lambda { |obj| obj.send(symbol) } 535: end 536: 537: if options[:if].respond_to?(:to_sym) then 538: options[:if] = options[:if].to_sym 539: end 540: 541: if options[:if].is_a?(Symbol) then 542: options[:if] = Contract::Check::Quack[options[:if]] 543: elsif options[:if].respond_to?(:call) then 544: callable = options[:if] 545: options[:if] = Contract::Check.block { |obj| callable.call(obj) } 546: end 547: 548: if options[:from] == self and options[:to] == self then 549: raise(ArgumentError, "Need to specify either :from or :to") 550: elsif options[:from] == options[:to] then 551: raise(ArgumentError, "Self-adaption: :from and :to both are " + 552: options[:to].inspect) 553: end 554: 555: unless options[:via] 556: raise(ArgumentError, "Need to specify how to adapt (use :via or block)") 557: end 558: 559: Contract.adaptions[options[:to]] << options 560: end