Class: EntitySchema::Contracts::Contract

Inherits:
Object
  • Object
show all
Defined in:
lib/entity_schema/contracts/contract.rb

Overview

Check data with strict contract, described with Hash-based DSL

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(rules) ⇒ Contract

Returns a new instance of Contract.



21
22
23
24
25
26
# File 'lib/entity_schema/contracts/contract.rb', line 21

def initialize(rules)
  @rules = rules.dup
  @rules.each_value { |rule| rule.transform_values! { |v| v.nil? ? [nil] : Array(v) } }
  @rules.each(&:freeze).freeze
  freeze
end

Class Method Details

.build(*arguments_arr) ⇒ Object



8
9
10
11
12
# File 'lib/entity_schema/contracts/contract.rb', line 8

def build(*arguments_arr)
  params      = arguments_arr.to_a
  options     = params.last.is_a?(Hash) ? params.pop : {}
  new(to_params_hash(params).merge(options))
end

.to_params_hash(arr) ⇒ Object



14
15
16
17
18
# File 'lib/entity_schema/contracts/contract.rb', line 14

def to_params_hash(arr)
  arr.each_with_object({}).with_index do |(value, params), i|
    params["argument #{i + 1}"] = value
  end
end

Instance Method Details

#+(other) ⇒ Object



28
29
30
31
32
33
# File 'lib/entity_schema/contracts/contract.rb', line 28

def +(other)
  args        = other.to_a
  options     = args.last.is_a?(Hash) ? args.pop : {}
  other_rules = to_params_hash(args).merge(options)
  merge(rules.merge(other_rules))
end

#call(*params, skip_unknown: false, **options) ⇒ Object

rubocop:disable Metrics/AbcSize



40
41
42
43
44
45
46
47
48
49
50
51
52
# File 'lib/entity_schema/contracts/contract.rb', line 40

def call(*params, skip_unknown: false, **options) # rubocop:disable Metrics/AbcSize
  keyvalue = to_params_hash(params).merge(options)
  keyvalue.each do |key, value|
    rules.key?(key) || skip_unknown || raise_unknown!(key, value)

    r = rules[key]
    next if r[:eq]&.any?         { |expectation| expectation == value }
    next if r[:type]&.any?       { |type| value.is_a?(type) }
    next if r[:respond_to]&.any? { |meth| value.respond_to?(meth) }
    raise_unexpected_value(r, key, value)
  end
  true
end

#merge(other) ⇒ Object



35
36
37
38
# File 'lib/entity_schema/contracts/contract.rb', line 35

def merge(other)
  other_rules = other.to_h
  self.class.new(rules.merge(other_rules))
end

#to_aObject



58
59
60
61
# File 'lib/entity_schema/contracts/contract.rb', line 58

def to_a
  params, options = to_arguments(rules)
  params << options
end

#to_hObject



54
55
56
# File 'lib/entity_schema/contracts/contract.rb', line 54

def to_h
  rules
end