module Contracts::CallWith
Constants
- SILENT_FAILURE
Public Instance Methods
call_with(this, *args, &blk)
click to toggle source
# File lib/contracts/contract/call_with.rb, line 4 def call_with(this, *args, &blk) args << blk if blk nil_block_appended = maybe_append_block!(args, blk) maybe_append_options!(args, blk) return if SILENT_FAILURE == catch(:return) do args_validator.validate_args_before_splat!(args) end return if SILENT_FAILURE == catch(:return) do args_validator.validate_splat_args_and_after!(args) end handle_result(this, args, blk, nil_block_appended) end
Private Instance Methods
args_validator()
click to toggle source
# File lib/contracts/contract/call_with.rb, line 32 def args_validator @args_validator ||= Contracts::ArgsValidator.new( klass: klass, method: method, contracts: self, args_contracts: args_contracts, args_validators: args_validators, splat_args_contract_index: splat_args_contract_index ) end
execute_args(this, args, blk)
click to toggle source
# File lib/contracts/contract/call_with.rb, line 72 def execute_args(this, args, blk) # a `call`-able method, like proc, block, lambda return method.call(*args, &blk) if method.respond_to?(:call) # original method name referrence method.send_to(this, *args, &blk) end
handle_result(this, args, blk, nil_block_appended)
click to toggle source
# File lib/contracts/contract/call_with.rb, line 23 def handle_result(this, args, blk, nil_block_appended) restore_args!(args, blk, nil_block_appended) result = execute_args(this, args, blk) validate_result(result) verify_invariants!(this) wrap_result_if_func(result) end
maybe_append_block!(args, blk)
click to toggle source
Explicitly append blk=nil if nil != Proc contract violation anticipated if we specified a proc in the contract but didn't pass one in, it's possible we are going to pass in a block instead. So lets append a nil to the list of args just so it doesn't fail.
a better way to handle this might be to take this into account before throwing a “mismatched # of args” error. returns true if it appended nil
# File lib/contracts/contract/call_with.rb, line 88 def maybe_append_block!(args, blk) return unless @has_proc_contract && !blk && needs_more_args?(args) args << nil true end
maybe_append_options!(args, blk)
click to toggle source
Explicitly append options={} if Hash contract is present Same thing for when we have named params but didn't pass any in. returns true if it appended {}
# File lib/contracts/contract/call_with.rb, line 103 def maybe_append_options!(args, blk) return unless @has_options_contract return args.insert(-2, {}) if use_penultimate_contract?(args) return args.insert(-1, {}) if use_last_contract?(args) end
needs_more_args?(args)
click to toggle source
# File lib/contracts/contract/call_with.rb, line 94 def needs_more_args?(args) is_splat = splat_args_contract_index more_args_expected = args.size < args_contracts.size (is_splat || more_args_expected) end
restore_args!(args, blk, nil_block_appended)
click to toggle source
Restore the args
-
if we put the block into args for validating
-
OR if we added a fake nil at the end because a block wasn't passed in.
# File lib/contracts/contract/call_with.rb, line 46 def restore_args!(args, blk, nil_block_appended) args.slice!(-1) if blk || nil_block_appended end
use_last_contract?(args)
click to toggle source
# File lib/contracts/contract/call_with.rb, line 109 def use_last_contract?(args) return if args[-1].is_a?(Hash) kinda_hash?(args_contracts[-1]) end
use_penultimate_contract?(args)
click to toggle source
# File lib/contracts/contract/call_with.rb, line 114 def use_penultimate_contract?(args) return if args[-2].is_a?(Hash) kinda_hash?(args_contracts[-2]) end
validate_result(result)
click to toggle source
# File lib/contracts/contract/call_with.rb, line 50 def validate_result(result) return if ret_validator.call(result) Contract.failure_callback( :arg => result, :contract => ret_contract, :class => klass, :method => method, :contracts => self, :return_value => true ) end
verify_invariants!(this)
click to toggle source
# File lib/contracts/contract/call_with.rb, line 62 def verify_invariants!(this) return unless this.respond_to?(:verify_invariants!) this.verify_invariants!(method) end
wrap_result_if_func(result)
click to toggle source
# File lib/contracts/contract/call_with.rb, line 67 def wrap_result_if_func(result) return result unless ret_contract.is_a?(Contracts::Func) Contract.new(klass, result, *ret_contract.contracts) end