Module: Handshake
- Defined in:
- lib/handshake.rb,
lib/handshake/version.rb,
lib/handshake/block_contract.rb,
lib/handshake/clause_methods.rb
Overview
:nodoc:
Defined Under Namespace
Modules: ClassMethods, ClauseMethods, InstanceMethods, VERSION Classes: AssertionFailed, Block, CheckedProc, Clause, ContractError, ContractViolation, Invariant, MethodCondition, MethodContract, ProcContract, Proxy
Class Method Summary collapse
-
.catch_contract(mesg = nil, &block) ⇒ Object
Catches any thrown :contract exception raised within the given block, appends the given message to the violation message, and re-raises the exception.
-
.included(base) ⇒ Object
When Handshake is included in a class, that class’s
new
method is overridden to provide custom functionality. -
.suppress! ⇒ Object
Suppress Handshake contract checking, for use in production code.
- .suppressed? ⇒ Boolean
Class Method Details
.catch_contract(mesg = nil, &block) ⇒ Object
Catches any thrown :contract exception raised within the given block, appends the given message to the violation message, and re-raises the exception.
16 17 18 19 20 21 22 23 24 25 |
# File 'lib/handshake.rb', line 16 def Handshake.catch_contract(mesg=nil, &block) # :nodoc: violation = catch(:contract, &block) if violation.is_a?(Exception) # Re-raise the violation with the given message, ensuring that the # callback stack begins with the caller of this method rather than # this method. = ( mesg.nil? ? "" : ( mesg + ": " ) ) + violation. raise violation.class, , caller end end |
.included(base) ⇒ Object
When Handshake is included in a class, that class’s new
method is overridden to provide custom functionality. A proxy object, returned in place of the real object, filters all external method calls through any contracts that have been defined. <b>N.B.:<b> Handshake is designed to act as a barrier between an object and its callers. However, anything that takes place within that barrier is not checked. This means that Handshake is, at the moment, unable to enforce contracts on methods called only internally, notably private methods.
46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 |
# File 'lib/handshake.rb', line 46 def Handshake.included(base) base.extend(ClassMethods) base.extend(ClauseMethods) base.send(:include, Test::Unit::Assertions) base.send(:include, Handshake::InstanceMethods) base.class_inheritable_array :invariants base.write_inheritable_array :invariants, [] base.class_inheritable_hash :method_contracts base.write_inheritable_hash :method_contracts, {} class << base alias :__new__ :new # Override the class-level new method of every class that includes # Contract and cause it to return a proxy object for the original. def new(*args, &block) return __new__(*args, &block) if Handshake.suppressed? Handshake.catch_contract("Contract violated in call to constructor of class #{self}") do if contract_defined? :initialize method_contracts[:initialize].check_accepts!(*args, &block) end end o = __new__(*args, &block) raise ContractError, "Could not instantiate object" if o.nil? Handshake.catch_contract("Invariant violated by constructor of class #{self}") do o.check_invariants! end Proxy.new o end end end |
.suppress! ⇒ Object
Suppress Handshake contract checking, for use in production code.
28 29 30 |
# File 'lib/handshake.rb', line 28 def Handshake.suppress! @suppress_handshake = true end |
.suppressed? ⇒ Boolean
32 33 34 35 |
# File 'lib/handshake.rb', line 32 def Handshake.suppressed? @suppress_handshake = false unless defined?(@suppress_handshake) @suppress_handshake end |