lib/nanoc/base/contracts_support.rb in nanoc-4.4.4 vs lib/nanoc/base/contracts_support.rb in nanoc-4.4.5

- old
+ new

@@ -27,29 +27,82 @@ None = Ignorer.instance ArrayOf = Ignorer.instance Or = Ignorer.instance Func = Ignorer.instance RespondTo = Ignorer.instance + Named = Ignorer.instance + IterOf = Ignorer.instance + HashOf = Ignorer.instance def contract(*args); end end module EnabledContracts + class AbstractContract + def self.[](*vals) + new(*vals) + end + end + + class Named < AbstractContract + def initialize(name) + @name = name + end + + def valid?(val) + val.is_a?(Kernel.const_get(@name)) + end + + def inspect + "#{self.class}(#{@name})" + end + end + + class IterOf < AbstractContract + def initialize(contract) + @contract = contract + end + + def valid?(val) + val.respond_to?(:each) && val.all? { |v| Contract.valid?(v, @contract) } + end + + def inspect + "#{self.class}(#{@contract})" + end + end + def contract(*args) Contract(*args) end end - def self.included(base) + def self.setup_once + @_contracts_support__setup ||= false + return @_contracts_support__should_enable if @_contracts_support__setup + @_contracts_support__setup = true + contracts_loadable = begin require 'contracts' true rescue LoadError false end - should_enable = contracts_loadable && !ENV.key?('DISABLE_CONTRACTS') + @_contracts_support__should_enable = contracts_loadable && !ENV.key?('DISABLE_CONTRACTS') + + if @_contracts_support__should_enable + # FIXME: ugly + ::Contracts.const_set('Named', EnabledContracts::Named) + ::Contracts.const_set('IterOf', EnabledContracts::IterOf) + end + + @_contracts_support__should_enable + end + + def self.included(base) + should_enable = setup_once if should_enable unless base.include?(::Contracts::Core) base.include(::Contracts::Core) base.extend(EnabledContracts)