dry-logic 0.1.4 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
 - data/Gemfile +0 -1
 - data/README.md +6 -2
 - data/lib/dry/logic/evaluator.rb +46 -0
 - data/lib/dry/logic/predicate.rb +3 -3
 - data/lib/dry/logic/result.rb +26 -126
 - data/lib/dry/logic/result/each.rb +10 -0
 - data/lib/dry/logic/result/multi.rb +14 -0
 - data/lib/dry/logic/result/named.rb +17 -0
 - data/lib/dry/logic/result/set.rb +10 -0
 - data/lib/dry/logic/result/value.rb +13 -0
 - data/lib/dry/logic/rule.rb +14 -36
 - data/lib/dry/logic/rule/attr.rb +3 -11
 - data/lib/dry/logic/rule/check.rb +23 -22
 - data/lib/dry/logic/rule/composite.rb +32 -12
 - data/lib/dry/logic/rule/each.rb +3 -3
 - data/lib/dry/logic/rule/key.rb +24 -5
 - data/lib/dry/logic/rule/negation.rb +15 -0
 - data/lib/dry/logic/rule/set.rb +9 -8
 - data/lib/dry/logic/rule/value.rb +15 -3
 - data/lib/dry/logic/rule_compiler.rb +8 -40
 - data/lib/dry/logic/version.rb +1 -1
 - data/spec/shared/predicates.rb +2 -0
 - data/spec/spec_helper.rb +1 -0
 - data/spec/unit/rule/attr_spec.rb +5 -5
 - data/spec/unit/rule/check_spec.rb +26 -39
 - data/spec/unit/rule/conjunction_spec.rb +4 -4
 - data/spec/unit/rule/disjunction_spec.rb +3 -3
 - data/spec/unit/rule/each_spec.rb +2 -2
 - data/spec/unit/rule/exclusive_disjunction_spec.rb +19 -0
 - data/spec/unit/rule/implication_spec.rb +2 -2
 - data/spec/unit/rule/key_spec.rb +103 -9
 - data/spec/unit/rule/set_spec.rb +7 -9
 - data/spec/unit/rule/value_spec.rb +29 -3
 - data/spec/unit/rule_compiler_spec.rb +21 -49
 - metadata +12 -9
 - data/lib/dry/logic/rule/group.rb +0 -21
 - data/lib/dry/logic/rule/result.rb +0 -33
 - data/rakelib/rubocop.rake +0 -18
 - data/spec/unit/rule/group_spec.rb +0 -12
 - data/spec/unit/rule/result_spec.rb +0 -102
 
    
        checksums.yaml
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            ---
         
     | 
| 
       2 
2 
     | 
    
         
             
            SHA1:
         
     | 
| 
       3 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       4 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: 556cffe1d07e756e85274f2af98b8d97245e4420
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: 86695fbdf83593baedb7dd73483c30f41f671280
         
     | 
| 
       5 
5 
     | 
    
         
             
            SHA512:
         
     | 
| 
       6 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       7 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: 05b63d57cfacd055926b256752698078dbca63afcf8bb03aff563cbecff5247e9dc66e999bad29cecc1fc5f37a15a5c6c76525cb1e6654f1c4915777825d5fa3
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: f1a65826b7049c3c5b0083b4c72feda8e911915898ff03a4d9acc5b4d6908954d9105edd36f611e535e0e0320b1f906f9ae658659a062b48ee18b564e1ab0abb
         
     | 
    
        data/Gemfile
    CHANGED
    
    
    
        data/README.md
    CHANGED
    
    | 
         @@ -28,8 +28,12 @@ require 'dry/logic/predicates' 
     | 
|
| 
       28 
28 
     | 
    
         | 
| 
       29 
29 
     | 
    
         
             
            include Dry::Logic
         
     | 
| 
       30 
30 
     | 
    
         | 
| 
       31 
     | 
    
         
            -
            user_present = Rule::Key.new( 
     | 
| 
       32 
     | 
    
         
            -
             
     | 
| 
      
 31 
     | 
    
         
            +
            user_present = Rule::Key.new(Predicates[:key?], name: :user)
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
            has_min_age = Rule::Key.new(
         
     | 
| 
      
 34 
     | 
    
         
            +
              Predicates[:key?]) & Rule::Value.new(:age, Predicates[:gt?].curry(18),
         
     | 
| 
      
 35 
     | 
    
         
            +
              name: :age
         
     | 
| 
      
 36 
     | 
    
         
            +
            )
         
     | 
| 
       33 
37 
     | 
    
         | 
| 
       34 
38 
     | 
    
         
             
            user_rule = user_present & has_min_age
         
     | 
| 
       35 
39 
     | 
    
         | 
| 
         @@ -0,0 +1,46 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Dry
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Logic
         
     | 
| 
      
 3 
     | 
    
         
            +
                class Evaluator
         
     | 
| 
      
 4 
     | 
    
         
            +
                  include Dry::Equalizer(:path)
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
                  attr_reader :path
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
                  class Set
         
     | 
| 
      
 9 
     | 
    
         
            +
                    include Dry::Equalizer(:evaluators)
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                    attr_reader :evaluators
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                    def self.new(paths)
         
     | 
| 
      
 14 
     | 
    
         
            +
                      super(paths.map { |path| Evaluator::Key.new(path) })
         
     | 
| 
      
 15 
     | 
    
         
            +
                    end
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                    def initialize(evaluators)
         
     | 
| 
      
 18 
     | 
    
         
            +
                      @evaluators = evaluators
         
     | 
| 
      
 19 
     | 
    
         
            +
                    end
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
                    def call(input)
         
     | 
| 
      
 22 
     | 
    
         
            +
                      evaluators.map { |evaluator| evaluator[input] }
         
     | 
| 
      
 23 
     | 
    
         
            +
                    end
         
     | 
| 
      
 24 
     | 
    
         
            +
                    alias_method :[], :call
         
     | 
| 
      
 25 
     | 
    
         
            +
                  end
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                  class Key < Evaluator
         
     | 
| 
      
 28 
     | 
    
         
            +
                    def call(input)
         
     | 
| 
      
 29 
     | 
    
         
            +
                      path.reduce(input) { |a, e| a[e] }
         
     | 
| 
      
 30 
     | 
    
         
            +
                    end
         
     | 
| 
      
 31 
     | 
    
         
            +
                    alias_method :[], :call
         
     | 
| 
      
 32 
     | 
    
         
            +
                  end
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
                  class Attr < Evaluator
         
     | 
| 
      
 35 
     | 
    
         
            +
                    def call(input)
         
     | 
| 
      
 36 
     | 
    
         
            +
                      path.reduce(input) { |a, e| a.public_send(e) }
         
     | 
| 
      
 37 
     | 
    
         
            +
                    end
         
     | 
| 
      
 38 
     | 
    
         
            +
                    alias_method :[], :call
         
     | 
| 
      
 39 
     | 
    
         
            +
                  end
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
                  def initialize(path)
         
     | 
| 
      
 42 
     | 
    
         
            +
                    @path = Array(path)
         
     | 
| 
      
 43 
     | 
    
         
            +
                  end
         
     | 
| 
      
 44 
     | 
    
         
            +
                end
         
     | 
| 
      
 45 
     | 
    
         
            +
              end
         
     | 
| 
      
 46 
     | 
    
         
            +
            end
         
     | 
    
        data/lib/dry/logic/predicate.rb
    CHANGED
    
    | 
         @@ -8,7 +8,7 @@ module Dry 
     | 
|
| 
       8 
8 
     | 
    
         
             
                end
         
     | 
| 
       9 
9 
     | 
    
         | 
| 
       10 
10 
     | 
    
         
             
                class Predicate
         
     | 
| 
       11 
     | 
    
         
            -
                  include Dry::Equalizer(:id)
         
     | 
| 
      
 11 
     | 
    
         
            +
                  include Dry::Equalizer(:id, :args)
         
     | 
| 
       12 
12 
     | 
    
         | 
| 
       13 
13 
     | 
    
         
             
                  attr_reader :id, :args, :fn
         
     | 
| 
       14 
14 
     | 
    
         | 
| 
         @@ -26,10 +26,10 @@ module Dry 
     | 
|
| 
       26 
26 
     | 
    
         
             
                    self.class.new(id, *args, &fn.curry.(*args))
         
     | 
| 
       27 
27 
     | 
    
         
             
                  end
         
     | 
| 
       28 
28 
     | 
    
         | 
| 
       29 
     | 
    
         
            -
                  def  
     | 
| 
      
 29 
     | 
    
         
            +
                  def to_ast
         
     | 
| 
       30 
30 
     | 
    
         
             
                    [:predicate, [id, args]]
         
     | 
| 
       31 
31 
     | 
    
         
             
                  end
         
     | 
| 
       32 
     | 
    
         
            -
                  alias_method :to_a, : 
     | 
| 
      
 32 
     | 
    
         
            +
                  alias_method :to_a, :to_ast
         
     | 
| 
       33 
33 
     | 
    
         
             
                end
         
     | 
| 
       34 
34 
     | 
    
         
             
              end
         
     | 
| 
       35 
35 
     | 
    
         
             
            end
         
     | 
    
        data/lib/dry/logic/result.rb
    CHANGED
    
    | 
         @@ -1,155 +1,55 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            module Dry
         
     | 
| 
       2 
2 
     | 
    
         
             
              module Logic
         
     | 
| 
       3 
     | 
    
         
            -
                def self.Result( 
     | 
| 
       4 
     | 
    
         
            -
                   
     | 
| 
       5 
     | 
    
         
            -
                  when Result
         
     | 
| 
       6 
     | 
    
         
            -
                    value.class.new(value.input, value.success?, rule)
         
     | 
| 
       7 
     | 
    
         
            -
                  when Array
         
     | 
| 
       8 
     | 
    
         
            -
                    Result::Set.new(input, value, rule)
         
     | 
| 
       9 
     | 
    
         
            -
                  else
         
     | 
| 
       10 
     | 
    
         
            -
                    Result::Value.new(input, value, rule)
         
     | 
| 
       11 
     | 
    
         
            -
                  end
         
     | 
| 
      
 3 
     | 
    
         
            +
                def self.Result(response, rule, input)
         
     | 
| 
      
 4 
     | 
    
         
            +
                  Result[rule].new(response, rule, input)
         
     | 
| 
       12 
5 
     | 
    
         
             
                end
         
     | 
| 
       13 
6 
     | 
    
         | 
| 
       14 
7 
     | 
    
         
             
                class Result
         
     | 
| 
       15 
8 
     | 
    
         
             
                  include Dry::Equalizer(:success?, :input, :rule)
         
     | 
| 
       16 
9 
     | 
    
         | 
| 
       17 
     | 
    
         
            -
                  attr_reader :input, : 
     | 
| 
       18 
     | 
    
         
            -
             
     | 
| 
       19 
     | 
    
         
            -
                  class Result::Set < Result
         
     | 
| 
       20 
     | 
    
         
            -
                    def success?
         
     | 
| 
       21 
     | 
    
         
            -
                      value.all?(&:success?)
         
     | 
| 
       22 
     | 
    
         
            -
                    end
         
     | 
| 
       23 
     | 
    
         
            -
             
     | 
| 
       24 
     | 
    
         
            -
                    def to_ary
         
     | 
| 
       25 
     | 
    
         
            -
                      indices = value.map { |v| v.failure? ? value.index(v) : nil }.compact
         
     | 
| 
       26 
     | 
    
         
            -
                      [:input, [name, input, value.values_at(*indices).map(&:to_ary)]]
         
     | 
| 
       27 
     | 
    
         
            -
                    end
         
     | 
| 
       28 
     | 
    
         
            -
                  end
         
     | 
| 
       29 
     | 
    
         
            -
             
     | 
| 
       30 
     | 
    
         
            -
                  class Result::Value < Result
         
     | 
| 
       31 
     | 
    
         
            -
                    def to_ary
         
     | 
| 
       32 
     | 
    
         
            -
                      [:input, [name, input, [rule.to_ary]]]
         
     | 
| 
       33 
     | 
    
         
            -
                    end
         
     | 
| 
       34 
     | 
    
         
            -
                    alias_method :to_a, :to_ary
         
     | 
| 
       35 
     | 
    
         
            -
                  end
         
     | 
| 
       36 
     | 
    
         
            -
             
     | 
| 
       37 
     | 
    
         
            -
                  class Result::LazyValue < Result
         
     | 
| 
       38 
     | 
    
         
            -
                    def to_ary
         
     | 
| 
       39 
     | 
    
         
            -
                      [:input, [rule.name, input, [rule.to_ary]]]
         
     | 
| 
       40 
     | 
    
         
            -
                    end
         
     | 
| 
       41 
     | 
    
         
            -
                    alias_method :to_a, :to_ary
         
     | 
| 
      
 10 
     | 
    
         
            +
                  attr_reader :input, :rule, :response, :success
         
     | 
| 
       42 
11 
     | 
    
         | 
| 
       43 
     | 
    
         
            -
             
     | 
| 
       44 
     | 
    
         
            -
             
     | 
| 
      
 12 
     | 
    
         
            +
                  def self.[](type)
         
     | 
| 
      
 13 
     | 
    
         
            +
                    case type
         
     | 
| 
      
 14 
     | 
    
         
            +
                    when Rule::Each then Result::Each
         
     | 
| 
      
 15 
     | 
    
         
            +
                    when Rule::Set then Result::Set
         
     | 
| 
      
 16 
     | 
    
         
            +
                    when Rule::Key, Rule::Attr, Rule::Check then Result::Named
         
     | 
| 
      
 17 
     | 
    
         
            +
                    else Result::Value
         
     | 
| 
       45 
18 
     | 
    
         
             
                    end
         
     | 
| 
       46 
19 
     | 
    
         
             
                  end
         
     | 
| 
       47 
20 
     | 
    
         | 
| 
       48 
     | 
    
         
            -
                   
     | 
| 
       49 
     | 
    
         
            -
                     
     | 
| 
       50 
     | 
    
         
            -
             
     | 
| 
       51 
     | 
    
         
            -
                    end
         
     | 
| 
       52 
     | 
    
         
            -
                    alias_method :to_a, :to_ary
         
     | 
| 
       53 
     | 
    
         
            -
             
     | 
| 
       54 
     | 
    
         
            -
                    def wrapped?
         
     | 
| 
       55 
     | 
    
         
            -
                      true
         
     | 
| 
       56 
     | 
    
         
            -
                    end
         
     | 
| 
       57 
     | 
    
         
            -
                  end
         
     | 
| 
       58 
     | 
    
         
            -
             
     | 
| 
       59 
     | 
    
         
            -
                  class Result::Verified < Result
         
     | 
| 
       60 
     | 
    
         
            -
                    attr_reader :predicate_id
         
     | 
| 
       61 
     | 
    
         
            -
             
     | 
| 
       62 
     | 
    
         
            -
                    def initialize(result, predicate_id)
         
     | 
| 
       63 
     | 
    
         
            -
                      @input = result.input
         
     | 
| 
       64 
     | 
    
         
            -
                      @value = result.value
         
     | 
| 
       65 
     | 
    
         
            -
                      @rule = result.rule
         
     | 
| 
       66 
     | 
    
         
            -
                      @name = result.name
         
     | 
| 
       67 
     | 
    
         
            -
                      @predicate_id = predicate_id
         
     | 
| 
       68 
     | 
    
         
            -
                    end
         
     | 
| 
       69 
     | 
    
         
            -
             
     | 
| 
       70 
     | 
    
         
            -
                    def call(*)
         
     | 
| 
       71 
     | 
    
         
            -
                      Logic.Result(input, success?, rule)
         
     | 
| 
       72 
     | 
    
         
            -
                    end
         
     | 
| 
       73 
     | 
    
         
            -
             
     | 
| 
       74 
     | 
    
         
            -
                    def to_ary
         
     | 
| 
       75 
     | 
    
         
            -
                      [:input, [name, input, [rule.to_ary]]]
         
     | 
| 
       76 
     | 
    
         
            -
                    end
         
     | 
| 
       77 
     | 
    
         
            -
                    alias_method :to_a, :to_ary
         
     | 
| 
       78 
     | 
    
         
            -
             
     | 
| 
       79 
     | 
    
         
            -
                    def success?
         
     | 
| 
       80 
     | 
    
         
            -
                      rule.predicate_id == predicate_id
         
     | 
| 
       81 
     | 
    
         
            -
                    end
         
     | 
| 
       82 
     | 
    
         
            -
                  end
         
     | 
| 
       83 
     | 
    
         
            -
             
     | 
| 
       84 
     | 
    
         
            -
                  def initialize(input, value, rule)
         
     | 
| 
       85 
     | 
    
         
            -
                    @input = input
         
     | 
| 
       86 
     | 
    
         
            -
                    @value = value
         
     | 
| 
      
 21 
     | 
    
         
            +
                  def initialize(response, rule, input)
         
     | 
| 
      
 22 
     | 
    
         
            +
                    @response = response
         
     | 
| 
      
 23 
     | 
    
         
            +
                    @success = response.respond_to?(:success?) ? response.success? : response
         
     | 
| 
       87 
24 
     | 
    
         
             
                    @rule = rule
         
     | 
| 
       88 
     | 
    
         
            -
                    @ 
     | 
| 
      
 25 
     | 
    
         
            +
                    @input = input
         
     | 
| 
       89 
26 
     | 
    
         
             
                  end
         
     | 
| 
       90 
27 
     | 
    
         | 
| 
       91 
     | 
    
         
            -
                  def  
     | 
| 
       92 
     | 
    
         
            -
                     
     | 
| 
      
 28 
     | 
    
         
            +
                  def [](name)
         
     | 
| 
      
 29 
     | 
    
         
            +
                    response[name] if response.respond_to?(:[])
         
     | 
| 
       93 
30 
     | 
    
         
             
                  end
         
     | 
| 
       94 
31 
     | 
    
         | 
| 
       95 
     | 
    
         
            -
                  def  
     | 
| 
       96 
     | 
    
         
            -
                     
     | 
| 
       97 
     | 
    
         
            -
                      Result::Verified.new(self, predicate_id)
         
     | 
| 
       98 
     | 
    
         
            -
                    else
         
     | 
| 
       99 
     | 
    
         
            -
                      self
         
     | 
| 
       100 
     | 
    
         
            -
                    end
         
     | 
| 
      
 32 
     | 
    
         
            +
                  def name
         
     | 
| 
      
 33 
     | 
    
         
            +
                    nil
         
     | 
| 
       101 
34 
     | 
    
         
             
                  end
         
     | 
| 
       102 
35 
     | 
    
         | 
| 
       103 
36 
     | 
    
         
             
                  def negated
         
     | 
| 
       104 
     | 
    
         
            -
                    self.class.new( 
     | 
| 
       105 
     | 
    
         
            -
                  end
         
     | 
| 
       106 
     | 
    
         
            -
             
     | 
| 
       107 
     | 
    
         
            -
                  def then(other)
         
     | 
| 
       108 
     | 
    
         
            -
                    if success?
         
     | 
| 
       109 
     | 
    
         
            -
                      other.(input)
         
     | 
| 
       110 
     | 
    
         
            -
                    else
         
     | 
| 
       111 
     | 
    
         
            -
                      Logic.Result(input, true, rule)
         
     | 
| 
       112 
     | 
    
         
            -
                    end
         
     | 
| 
       113 
     | 
    
         
            -
                  end
         
     | 
| 
       114 
     | 
    
         
            -
             
     | 
| 
       115 
     | 
    
         
            -
                  def and(other)
         
     | 
| 
       116 
     | 
    
         
            -
                    if success?
         
     | 
| 
       117 
     | 
    
         
            -
                      other.(input)
         
     | 
| 
       118 
     | 
    
         
            -
                    else
         
     | 
| 
       119 
     | 
    
         
            -
                      self
         
     | 
| 
       120 
     | 
    
         
            -
                    end
         
     | 
| 
       121 
     | 
    
         
            -
                  end
         
     | 
| 
       122 
     | 
    
         
            -
             
     | 
| 
       123 
     | 
    
         
            -
                  def or(other)
         
     | 
| 
       124 
     | 
    
         
            -
                    if success?
         
     | 
| 
       125 
     | 
    
         
            -
                      self
         
     | 
| 
       126 
     | 
    
         
            -
                    else
         
     | 
| 
       127 
     | 
    
         
            -
                      other.(input)
         
     | 
| 
       128 
     | 
    
         
            -
                    end
         
     | 
| 
       129 
     | 
    
         
            -
                  end
         
     | 
| 
       130 
     | 
    
         
            -
             
     | 
| 
       131 
     | 
    
         
            -
                  def xor(other)
         
     | 
| 
       132 
     | 
    
         
            -
                    other_result = other.(input)
         
     | 
| 
       133 
     | 
    
         
            -
                    value = success? ^ other_result.success?
         
     | 
| 
       134 
     | 
    
         
            -
             
     | 
| 
       135 
     | 
    
         
            -
                    if other_result.wrapped?
         
     | 
| 
       136 
     | 
    
         
            -
                      Result::Wrapped.new(input, value, rule)
         
     | 
| 
       137 
     | 
    
         
            -
                    else
         
     | 
| 
       138 
     | 
    
         
            -
                      Logic.Result(other_result.input, value, rule)
         
     | 
| 
       139 
     | 
    
         
            -
                    end
         
     | 
| 
      
 37 
     | 
    
         
            +
                    self.class.new(!success, rule, input)
         
     | 
| 
       140 
38 
     | 
    
         
             
                  end
         
     | 
| 
       141 
39 
     | 
    
         | 
| 
       142 
40 
     | 
    
         
             
                  def success?
         
     | 
| 
       143 
     | 
    
         
            -
                    @ 
     | 
| 
      
 41 
     | 
    
         
            +
                    @success
         
     | 
| 
       144 
42 
     | 
    
         
             
                  end
         
     | 
| 
       145 
43 
     | 
    
         | 
| 
       146 
44 
     | 
    
         
             
                  def failure?
         
     | 
| 
       147 
     | 
    
         
            -
                    ! 
     | 
| 
       148 
     | 
    
         
            -
                  end
         
     | 
| 
       149 
     | 
    
         
            -
             
     | 
| 
       150 
     | 
    
         
            -
                  def wrapped?
         
     | 
| 
       151 
     | 
    
         
            -
                    false
         
     | 
| 
      
 45 
     | 
    
         
            +
                    !success?
         
     | 
| 
       152 
46 
     | 
    
         
             
                  end
         
     | 
| 
       153 
47 
     | 
    
         
             
                end
         
     | 
| 
       154 
48 
     | 
    
         
             
              end
         
     | 
| 
       155 
49 
     | 
    
         
             
            end
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
            require 'dry/logic/result/value'
         
     | 
| 
      
 52 
     | 
    
         
            +
            require 'dry/logic/result/named'
         
     | 
| 
      
 53 
     | 
    
         
            +
            require 'dry/logic/result/multi'
         
     | 
| 
      
 54 
     | 
    
         
            +
            require 'dry/logic/result/each'
         
     | 
| 
      
 55 
     | 
    
         
            +
            require 'dry/logic/result/set'
         
     | 
| 
         @@ -0,0 +1,14 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Dry
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Logic
         
     | 
| 
      
 3 
     | 
    
         
            +
                class Result::Multi < Result
         
     | 
| 
      
 4 
     | 
    
         
            +
                  def success?
         
     | 
| 
      
 5 
     | 
    
         
            +
                    success.all?(&:success?)
         
     | 
| 
      
 6 
     | 
    
         
            +
                  end
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
                  def failures
         
     | 
| 
      
 9 
     | 
    
         
            +
                    indices = success.map { |v| v.failure? ? success.index(v) : nil }.compact
         
     | 
| 
      
 10 
     | 
    
         
            +
                    success.values_at(*indices)
         
     | 
| 
      
 11 
     | 
    
         
            +
                  end
         
     | 
| 
      
 12 
     | 
    
         
            +
                end
         
     | 
| 
      
 13 
     | 
    
         
            +
              end
         
     | 
| 
      
 14 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,17 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Dry
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Logic
         
     | 
| 
      
 3 
     | 
    
         
            +
                class Result::Named < Result::Value
         
     | 
| 
      
 4 
     | 
    
         
            +
                  def name
         
     | 
| 
      
 5 
     | 
    
         
            +
                    rule.name
         
     | 
| 
      
 6 
     | 
    
         
            +
                  end
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
                  def to_ast
         
     | 
| 
      
 9 
     | 
    
         
            +
                    if response.respond_to?(:to_ast) && !response.is_a?(Result)
         
     | 
| 
      
 10 
     | 
    
         
            +
                      response.to_ast
         
     | 
| 
      
 11 
     | 
    
         
            +
                    else
         
     | 
| 
      
 12 
     | 
    
         
            +
                      [:input, [rule.name, super]]
         
     | 
| 
      
 13 
     | 
    
         
            +
                    end
         
     | 
| 
      
 14 
     | 
    
         
            +
                  end
         
     | 
| 
      
 15 
     | 
    
         
            +
                end
         
     | 
| 
      
 16 
     | 
    
         
            +
              end
         
     | 
| 
      
 17 
     | 
    
         
            +
            end
         
     | 
    
        data/lib/dry/logic/rule.rb
    CHANGED
    
    | 
         @@ -1,31 +1,15 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            module Dry
         
     | 
| 
       2 
2 
     | 
    
         
             
              module Logic
         
     | 
| 
       3 
3 
     | 
    
         
             
                class Rule
         
     | 
| 
       4 
     | 
    
         
            -
                  include Dry::Equalizer(: 
     | 
| 
      
 4 
     | 
    
         
            +
                  include Dry::Equalizer(:predicate, :options)
         
     | 
| 
       5 
5 
     | 
    
         | 
| 
       6 
     | 
    
         
            -
                  attr_reader : 
     | 
| 
      
 6 
     | 
    
         
            +
                  attr_reader :predicate
         
     | 
| 
       7 
7 
     | 
    
         | 
| 
       8 
     | 
    
         
            -
                   
     | 
| 
       9 
     | 
    
         
            -
                    include Dry::Equalizer(:rule)
         
     | 
| 
      
 8 
     | 
    
         
            +
                  attr_reader :options
         
     | 
| 
       10 
9 
     | 
    
         | 
| 
       11 
     | 
    
         
            -
             
     | 
| 
       12 
     | 
    
         
            -
             
     | 
| 
       13 
     | 
    
         
            -
                    def initialize(rule)
         
     | 
| 
       14 
     | 
    
         
            -
                      @rule = rule
         
     | 
| 
       15 
     | 
    
         
            -
                    end
         
     | 
| 
       16 
     | 
    
         
            -
             
     | 
| 
       17 
     | 
    
         
            -
                    def call(*args)
         
     | 
| 
       18 
     | 
    
         
            -
                      rule.(*args).negated
         
     | 
| 
       19 
     | 
    
         
            -
                    end
         
     | 
| 
       20 
     | 
    
         
            -
             
     | 
| 
       21 
     | 
    
         
            -
                    def to_ary
         
     | 
| 
       22 
     | 
    
         
            -
                      [:not, rule.to_ary]
         
     | 
| 
       23 
     | 
    
         
            -
                    end
         
     | 
| 
       24 
     | 
    
         
            -
                  end
         
     | 
| 
       25 
     | 
    
         
            -
             
     | 
| 
       26 
     | 
    
         
            -
                  def initialize(name, predicate)
         
     | 
| 
       27 
     | 
    
         
            -
                    @name = name
         
     | 
| 
      
 10 
     | 
    
         
            +
                  def initialize(predicate, options = {})
         
     | 
| 
       28 
11 
     | 
    
         
             
                    @predicate = predicate
         
     | 
| 
      
 12 
     | 
    
         
            +
                    @options = options
         
     | 
| 
       29 
13 
     | 
    
         
             
                  end
         
     | 
| 
       30 
14 
     | 
    
         | 
| 
       31 
15 
     | 
    
         
             
                  def predicate_id
         
     | 
| 
         @@ -33,18 +17,9 @@ module Dry 
     | 
|
| 
       33 
17 
     | 
    
         
             
                  end
         
     | 
| 
       34 
18 
     | 
    
         | 
| 
       35 
19 
     | 
    
         
             
                  def type
         
     | 
| 
       36 
     | 
    
         
            -
                     
     | 
| 
       37 
     | 
    
         
            -
                  end
         
     | 
| 
       38 
     | 
    
         
            -
             
     | 
| 
       39 
     | 
    
         
            -
                  def call(*args)
         
     | 
| 
       40 
     | 
    
         
            -
                    Logic.Result(args, predicate.call, self)
         
     | 
| 
      
 20 
     | 
    
         
            +
                    raise NotImplementedError
         
     | 
| 
       41 
21 
     | 
    
         
             
                  end
         
     | 
| 
       42 
22 
     | 
    
         | 
| 
       43 
     | 
    
         
            -
                  def to_ary
         
     | 
| 
       44 
     | 
    
         
            -
                    [type, [name, predicate.to_ary]]
         
     | 
| 
       45 
     | 
    
         
            -
                  end
         
     | 
| 
       46 
     | 
    
         
            -
                  alias_method :to_a, :to_ary
         
     | 
| 
       47 
     | 
    
         
            -
             
     | 
| 
       48 
23 
     | 
    
         
             
                  def and(other)
         
     | 
| 
       49 
24 
     | 
    
         
             
                    Conjunction.new(self, other)
         
     | 
| 
       50 
25 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -70,24 +45,27 @@ module Dry 
     | 
|
| 
       70 
45 
     | 
    
         
             
                  end
         
     | 
| 
       71 
46 
     | 
    
         | 
| 
       72 
47 
     | 
    
         
             
                  def new(predicate)
         
     | 
| 
       73 
     | 
    
         
            -
                    self.class.new( 
     | 
| 
      
 48 
     | 
    
         
            +
                    self.class.new(predicate, options)
         
     | 
| 
       74 
49 
     | 
    
         
             
                  end
         
     | 
| 
       75 
50 
     | 
    
         | 
| 
       76 
51 
     | 
    
         
             
                  def curry(*args)
         
     | 
| 
       77 
     | 
    
         
            -
                    self.class.new( 
     | 
| 
      
 52 
     | 
    
         
            +
                    self.class.new(predicate.curry(*args), options)
         
     | 
| 
      
 53 
     | 
    
         
            +
                  end
         
     | 
| 
      
 54 
     | 
    
         
            +
             
     | 
| 
      
 55 
     | 
    
         
            +
                  def each?
         
     | 
| 
      
 56 
     | 
    
         
            +
                    predicate.is_a?(Rule::Each)
         
     | 
| 
       78 
57 
     | 
    
         
             
                  end
         
     | 
| 
       79 
58 
     | 
    
         
             
                end
         
     | 
| 
       80 
59 
     | 
    
         
             
              end
         
     | 
| 
       81 
60 
     | 
    
         
             
            end
         
     | 
| 
       82 
61 
     | 
    
         | 
| 
      
 62 
     | 
    
         
            +
            require 'dry/logic/rule/value'
         
     | 
| 
       83 
63 
     | 
    
         
             
            require 'dry/logic/rule/key'
         
     | 
| 
       84 
64 
     | 
    
         
             
            require 'dry/logic/rule/attr'
         
     | 
| 
       85 
     | 
    
         
            -
            require 'dry/logic/rule/value'
         
     | 
| 
       86 
65 
     | 
    
         
             
            require 'dry/logic/rule/each'
         
     | 
| 
       87 
66 
     | 
    
         
             
            require 'dry/logic/rule/set'
         
     | 
| 
       88 
67 
     | 
    
         
             
            require 'dry/logic/rule/composite'
         
     | 
| 
      
 68 
     | 
    
         
            +
            require 'dry/logic/rule/negation'
         
     | 
| 
       89 
69 
     | 
    
         
             
            require 'dry/logic/rule/check'
         
     | 
| 
       90 
     | 
    
         
            -
            require 'dry/logic/rule/result'
         
     | 
| 
       91 
     | 
    
         
            -
            require 'dry/logic/rule/group'
         
     | 
| 
       92 
70 
     | 
    
         | 
| 
       93 
71 
     | 
    
         
             
            require 'dry/logic/result'
         
     |