dry-logic 0.2.3 → 0.3.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/CHANGELOG.md +15 -1
- data/README.md +14 -7
- data/examples/basic.rb +8 -2
- data/lib/dry/logic/predicate.rb +72 -7
- data/lib/dry/logic/predicates.rb +4 -0
- data/lib/dry/logic/result/each.rb +1 -1
- data/lib/dry/logic/result/set.rb +1 -1
- data/lib/dry/logic/result/value.rb +5 -1
- data/lib/dry/logic/rule.rb +12 -1
- data/lib/dry/logic/rule/attr.rb +2 -2
- data/lib/dry/logic/rule/check.rb +1 -1
- data/lib/dry/logic/rule/composite.rb +12 -4
- data/lib/dry/logic/rule/key.rb +4 -3
- data/lib/dry/logic/rule/set.rb +8 -0
- data/lib/dry/logic/rule/value.rb +25 -2
- data/lib/dry/logic/rule_compiler.rb +9 -2
- data/lib/dry/logic/version.rb +1 -1
- data/spec/shared/predicates.rb +4 -4
- data/spec/unit/predicate_spec.rb +89 -1
- data/spec/unit/predicates/array_spec.rb +41 -0
- data/spec/unit/predicates/type_spec.rb +35 -0
- data/spec/unit/rule/check_spec.rb +3 -2
- data/spec/unit/rule/each_spec.rb +2 -2
- data/spec/unit/rule/key_spec.rb +3 -3
- data/spec/unit/rule/set_spec.rb +2 -2
- data/spec/unit/rule/value_spec.rb +33 -2
- data/spec/unit/rule_compiler_spec.rb +13 -13
- metadata +8 -3
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA1:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 0ea86d568127098e2777868066c2026dbc380eb9
         | 
| 4 | 
            +
              data.tar.gz: 5553735b89ab2ef6a1c5bdd3f24874bab46c2581
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: c943b1c67b55618b3e3fa1e982e371614a3e34c0ec2ca7457c775e755335a9579f52434d50545b411bf053f3c8e5a72209bdc86a58d7f13abef521df92b1fde5
         | 
| 7 | 
            +
              data.tar.gz: 87598a0a72b1196d966464b1a731746922613fa8eb72cfa3d002ecfe3dee917502126bcfb2e506ae67c958335a6343b05db131e7012d1a0c64d74320d4e3d2d6
         | 
    
        data/CHANGELOG.md
    CHANGED
    
    | @@ -1,3 +1,18 @@ | |
| 1 | 
            +
            # v0.3.0 2016-07-01
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            ### Added
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            * `:type?` predicate imported from dry-types (solnic)
         | 
| 6 | 
            +
            * `Rule#curry` interface (solnic)
         | 
| 7 | 
            +
             | 
| 8 | 
            +
            ### Changed
         | 
| 9 | 
            +
             | 
| 10 | 
            +
            * Predicates AST now includes information about args (names & possible values) (fran-worley + solnic)
         | 
| 11 | 
            +
            * Predicates raise errors when they are called with invalid arity (fran-worley + solnic)
         | 
| 12 | 
            +
            * Rules no longer evaluate input twice when building result objects (solnic)
         | 
| 13 | 
            +
             | 
| 14 | 
            +
            [Compare v0.2.3...v0.3.0](https://github.com/dryrb/dry-logic/compare/v0.2.3...v0.3.0)
         | 
| 15 | 
            +
             | 
| 1 16 | 
             
            # v0.2.3 2016-05-11
         | 
| 2 17 |  | 
| 3 18 | 
             
            ### Added
         | 
| @@ -11,7 +26,6 @@ | |
| 11 26 |  | 
| 12 27 | 
             
            [Compare v0.2.2...v0.2.3](https://github.com/dryrb/dry-logic/compare/v0.2.2...v0.2.3)
         | 
| 13 28 |  | 
| 14 | 
            -
             | 
| 15 29 | 
             
            # v0.2.2 2016-03-30
         | 
| 16 30 |  | 
| 17 31 | 
             
            ### Added
         | 
    
        data/README.md
    CHANGED
    
    | @@ -28,20 +28,27 @@ require 'dry/logic/predicates' | |
| 28 28 |  | 
| 29 29 | 
             
            include Dry::Logic
         | 
| 30 30 |  | 
| 31 | 
            -
            user_present = Rule::Key.new(Predicates[: | 
| 31 | 
            +
            user_present = Rule::Key.new(Predicates[:filled?], name: :user)
         | 
| 32 32 |  | 
| 33 | 
            -
            has_min_age = Rule::Key.new(
         | 
| 34 | 
            -
               | 
| 35 | 
            -
              name: :age
         | 
| 36 | 
            -
            )
         | 
| 33 | 
            +
            has_min_age = Rule::Key.new(Predicates[:int?], name: [:user, :age])
         | 
| 34 | 
            +
              & Rule::Key.new(Predicates[:gt?].curry(18), name: [:user, :age])
         | 
| 37 35 |  | 
| 38 36 | 
             
            user_rule = user_present & has_min_age
         | 
| 39 37 |  | 
| 40 38 | 
             
            user_rule.(user: { age: 19 })
         | 
| 41 | 
            -
            # #<Dry::Logic::Result:: | 
| 39 | 
            +
            # #<Dry::Logic::Result::Named success?=true input={:user=>{:age=>19}} rule=#<Dry::Logic::Rule::Key predicate=#<Dry::Logic::Predicate id=:gt? args=[18, 19]> options={:evaluator=>#<Dry::Logic::Evaluator::Key path=[:user, :age]>, :name=>[:user, :age]}>>
         | 
| 42 40 |  | 
| 43 41 | 
             
            user_rule.(user: { age: 18 })
         | 
| 44 | 
            -
            # #<Dry::Logic::Result:: | 
| 42 | 
            +
            # #<Dry::Logic::Result::Named success?=false input={:user=>{:age=>18}} rule=#<Dry::Logic::Rule::Key predicate=#<Dry::Logic::Predicate id=:gt? args=[18, 18]> options={:evaluator=>#<Dry::Logic::Evaluator::Key path=[:user, :age]>, :name=>[:user, :age]}>>
         | 
| 43 | 
            +
             | 
| 44 | 
            +
            user_rule.(user: { age: 'seventeen' }).inspect
         | 
| 45 | 
            +
            #<Dry::Logic::Result::Named success?=false input={:user=>{:age=>"seventeen"}} rule=#<Dry::Logic::Rule::Key predicate=#<Dry::Logic::Predicate id=:int? args=["seventeen"]> options={:evaluator=>#<Dry::Logic::Evaluator::Key path=[:user, :age]>, :name=>[:user, :age]}>>
         | 
| 46 | 
            +
             | 
| 47 | 
            +
            user_rule.(user: { }).inspect
         | 
| 48 | 
            +
            #<Dry::Logic::Result::Named success?=false input={:user=>{}} rule=#<Dry::Logic::Rule::Key predicate=#<Dry::Logic::Predicate id=:filled? args=[{}]> options={:evaluator=>#<Dry::Logic::Evaluator::Key path=[:user]>, :name=>:user}>>
         | 
| 49 | 
            +
             | 
| 50 | 
            +
            puts user_rule.({}).inspect
         | 
| 51 | 
            +
            #<Dry::Logic::Result::Named success?=false input={} rule=#<Dry::Logic::Rule::Key predicate=#<Dry::Logic::Predicate id=:filled? args=[nil]> options={:evaluator=>#<Dry::Logic::Evaluator::Key path=[:user]>, :name=>:user}>>
         | 
| 45 52 | 
             
            ```
         | 
| 46 53 |  | 
| 47 54 | 
             
            ## License
         | 
    
        data/examples/basic.rb
    CHANGED
    
    | @@ -3,11 +3,17 @@ require 'dry/logic/predicates' | |
| 3 3 |  | 
| 4 4 | 
             
            include Dry::Logic
         | 
| 5 5 |  | 
| 6 | 
            -
            user_present = Rule::Key.new( | 
| 7 | 
            -
            has_min_age = Rule::Key.new(: | 
| 6 | 
            +
            user_present = Rule::Key.new(Predicates[:filled?], name: :user)
         | 
| 7 | 
            +
            has_min_age = Rule::Key.new(Predicates[:int?], name: [:user, :age]) & Rule::Key.new(Predicates[:gt?].curry(18), name: [:user, :age])
         | 
| 8 8 |  | 
| 9 9 | 
             
            user_rule = user_present & has_min_age
         | 
| 10 10 |  | 
| 11 11 | 
             
            puts user_rule.(user: { age: 19 }).inspect
         | 
| 12 12 |  | 
| 13 13 | 
             
            puts user_rule.(user: { age: 18 }).inspect
         | 
| 14 | 
            +
             | 
| 15 | 
            +
            puts user_rule.(user: { age: 'seventeen' }).inspect
         | 
| 16 | 
            +
             | 
| 17 | 
            +
            puts user_rule.(user: { }).inspect
         | 
| 18 | 
            +
             | 
| 19 | 
            +
            puts user_rule.({}).inspect
         | 
    
        data/lib/dry/logic/predicate.rb
    CHANGED
    
    | @@ -3,33 +3,98 @@ module Dry | |
| 3 3 | 
             
                def self.Predicate(block)
         | 
| 4 4 | 
             
                  case block
         | 
| 5 5 | 
             
                  when Method then Predicate.new(block.name, &block)
         | 
| 6 | 
            +
                  when UnboundMethod then Predicate.new(block.name, fn: block)
         | 
| 6 7 | 
             
                  else raise ArgumentError, 'predicate needs an :id'
         | 
| 7 8 | 
             
                  end
         | 
| 8 9 | 
             
                end
         | 
| 9 10 |  | 
| 10 11 | 
             
                class Predicate
         | 
| 12 | 
            +
                  Undefined = Class.new {
         | 
| 13 | 
            +
                    def inspect
         | 
| 14 | 
            +
                      "undefined"
         | 
| 15 | 
            +
                    end
         | 
| 16 | 
            +
                    alias_method :to_s, :inspect
         | 
| 17 | 
            +
                  }.new.freeze
         | 
| 18 | 
            +
             | 
| 11 19 | 
             
                  include Dry::Equalizer(:id, :args)
         | 
| 12 20 |  | 
| 13 | 
            -
                  attr_reader :id, :args, :fn
         | 
| 21 | 
            +
                  attr_reader :id, :args, :fn, :arity
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                  class Curried < Predicate
         | 
| 24 | 
            +
                    def call(*args)
         | 
| 25 | 
            +
                      all_args = @args + args
         | 
| 14 26 |  | 
| 15 | 
            -
             | 
| 27 | 
            +
                      if all_args.size == arity
         | 
| 28 | 
            +
                        super(*args)
         | 
| 29 | 
            +
                      else
         | 
| 30 | 
            +
                        curry(*args)
         | 
| 31 | 
            +
                      end
         | 
| 32 | 
            +
                    end
         | 
| 33 | 
            +
                    alias_method :[], :call
         | 
| 34 | 
            +
                  end
         | 
| 35 | 
            +
             | 
| 36 | 
            +
                  def initialize(id, args: [], fn: nil, arity: nil, &block)
         | 
| 16 37 | 
             
                    @id = id
         | 
| 17 | 
            -
                    @fn = block
         | 
| 18 38 | 
             
                    @args = args
         | 
| 39 | 
            +
                    @fn = fn || block
         | 
| 40 | 
            +
                    @arity = arity || @fn.arity
         | 
| 19 41 | 
             
                  end
         | 
| 20 42 |  | 
| 43 | 
            +
                  #as long as we keep track of the args, we don't actually need to curry the proc...
         | 
| 44 | 
            +
                  #if we never curry the proc then fn.arity & fn.parameters stay intact
         | 
| 45 | 
            +
                  def curry(*args)
         | 
| 46 | 
            +
                    if args.size > 0
         | 
| 47 | 
            +
                      all_args = @args + args
         | 
| 48 | 
            +
                      size = all_args.size
         | 
| 49 | 
            +
             | 
| 50 | 
            +
                      if size <= arity
         | 
| 51 | 
            +
                        Curried.new(id, args: all_args, fn: fn, arity: arity)
         | 
| 52 | 
            +
                      else
         | 
| 53 | 
            +
                        raise_arity_error(all_args.size)
         | 
| 54 | 
            +
                      end
         | 
| 55 | 
            +
                    else
         | 
| 56 | 
            +
                      self
         | 
| 57 | 
            +
                    end
         | 
| 58 | 
            +
                  end
         | 
| 59 | 
            +
             | 
| 60 | 
            +
                  # @api public
         | 
| 61 | 
            +
                  def bind(object)
         | 
| 62 | 
            +
                    self.class.new(id, *args, &fn.bind(object))
         | 
| 63 | 
            +
                  end
         | 
| 64 | 
            +
             | 
| 65 | 
            +
                  #enables a rule to call with its params & have them ignored if the
         | 
| 66 | 
            +
                  #predicate doesn't need them.
         | 
| 67 | 
            +
                  #if @args.size == arity then we should ignore called args
         | 
| 21 68 | 
             
                  def call(*args)
         | 
| 22 | 
            -
                     | 
| 69 | 
            +
                    all_args = @args + args
         | 
| 70 | 
            +
                    size = all_args.size
         | 
| 71 | 
            +
             | 
| 72 | 
            +
                    if size == arity
         | 
| 73 | 
            +
                      fn.(*all_args)
         | 
| 74 | 
            +
                    else
         | 
| 75 | 
            +
                      raise_arity_error(size)
         | 
| 76 | 
            +
                    end
         | 
| 23 77 | 
             
                  end
         | 
| 78 | 
            +
                  alias_method :[], :call
         | 
| 24 79 |  | 
| 25 | 
            -
                  def  | 
| 26 | 
            -
                     | 
| 80 | 
            +
                  def parameters
         | 
| 81 | 
            +
                    fn.parameters
         | 
| 27 82 | 
             
                  end
         | 
| 28 83 |  | 
| 29 84 | 
             
                  def to_ast
         | 
| 30 | 
            -
                    [:predicate, [id,  | 
| 85 | 
            +
                    [:predicate, [id, args_with_names]]
         | 
| 31 86 | 
             
                  end
         | 
| 32 87 | 
             
                  alias_method :to_a, :to_ast
         | 
| 88 | 
            +
             | 
| 89 | 
            +
                  private
         | 
| 90 | 
            +
             | 
| 91 | 
            +
                  def args_with_names
         | 
| 92 | 
            +
                    parameters.map(&:last).zip(args + Array.new(arity - args.size, Undefined))
         | 
| 93 | 
            +
                  end
         | 
| 94 | 
            +
             | 
| 95 | 
            +
                  def raise_arity_error(args_size)
         | 
| 96 | 
            +
                    raise ArgumentError, "wrong number of arguments (#{args_size} for #{arity})"
         | 
| 97 | 
            +
                  end
         | 
| 33 98 | 
             
                end
         | 
| 34 99 | 
             
              end
         | 
| 35 100 | 
             
            end
         | 
    
        data/lib/dry/logic/predicates.rb
    CHANGED
    
    
    
        data/lib/dry/logic/result/set.rb
    CHANGED
    
    
| @@ -5,9 +5,13 @@ module Dry | |
| 5 5 | 
             
                    if response.respond_to?(:to_ast)
         | 
| 6 6 | 
             
                      response.to_ast
         | 
| 7 7 | 
             
                    else
         | 
| 8 | 
            -
                      [:result, [ | 
| 8 | 
            +
                      [:result, [input, rule.to_ast]]
         | 
| 9 9 | 
             
                    end
         | 
| 10 10 | 
             
                  end
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                  def input
         | 
| 13 | 
            +
                    rule.input != Predicate::Undefined ? rule.input : super
         | 
| 14 | 
            +
                  end
         | 
| 11 15 | 
             
                end
         | 
| 12 16 | 
             
              end
         | 
| 13 17 | 
             
            end
         | 
    
        data/lib/dry/logic/rule.rb
    CHANGED
    
    | @@ -7,6 +7,13 @@ module Dry | |
| 7 7 |  | 
| 8 8 | 
             
                  attr_reader :options
         | 
| 9 9 |  | 
| 10 | 
            +
                  def self.method_added(meth)
         | 
| 11 | 
            +
                    super
         | 
| 12 | 
            +
                    if meth == :call
         | 
| 13 | 
            +
                      alias_method :[], :call
         | 
| 14 | 
            +
                    end
         | 
| 15 | 
            +
                  end
         | 
| 16 | 
            +
             | 
| 10 17 | 
             
                  def initialize(predicate, options = {})
         | 
| 11 18 | 
             
                    @predicate = predicate
         | 
| 12 19 | 
             
                    @options = options
         | 
| @@ -49,7 +56,11 @@ module Dry | |
| 49 56 | 
             
                  end
         | 
| 50 57 |  | 
| 51 58 | 
             
                  def curry(*args)
         | 
| 52 | 
            -
                     | 
| 59 | 
            +
                    if arity > 0
         | 
| 60 | 
            +
                      new(predicate.curry(*args))
         | 
| 61 | 
            +
                    else
         | 
| 62 | 
            +
                      self
         | 
| 63 | 
            +
                    end
         | 
| 53 64 | 
             
                  end
         | 
| 54 65 |  | 
| 55 66 | 
             
                  def each?
         | 
    
        data/lib/dry/logic/rule/attr.rb
    CHANGED
    
    
    
        data/lib/dry/logic/rule/check.rb
    CHANGED
    
    | @@ -21,7 +21,7 @@ module Dry | |
| 21 21 | 
             
                  def call(input)
         | 
| 22 22 | 
             
                    args = evaluator[input].reverse
         | 
| 23 23 | 
             
                    *head, tail = args
         | 
| 24 | 
            -
                    Logic.Result(predicate.curry(*head).(tail),  | 
| 24 | 
            +
                    Logic.Result(predicate.curry(*head).(tail), curry(*args), input)
         | 
| 25 25 | 
             
                  end
         | 
| 26 26 |  | 
| 27 27 | 
             
                  def evaluate(input)
         | 
| @@ -10,6 +10,18 @@ module Dry | |
| 10 10 | 
             
                    @right = right
         | 
| 11 11 | 
             
                  end
         | 
| 12 12 |  | 
| 13 | 
            +
                  def arity
         | 
| 14 | 
            +
                    -1
         | 
| 15 | 
            +
                  end
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                  def input
         | 
| 18 | 
            +
                    Predicate::Undefined
         | 
| 19 | 
            +
                  end
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                  def curry(*args)
         | 
| 22 | 
            +
                    self.class.new(left.curry(*args), right.curry(*args))
         | 
| 23 | 
            +
                  end
         | 
| 24 | 
            +
             | 
| 13 25 | 
             
                  def name
         | 
| 14 26 | 
             
                    :"#{left.name}_#{type}_#{right.name}"
         | 
| 15 27 | 
             
                  end
         | 
| @@ -71,10 +83,6 @@ module Dry | |
| 71 83 | 
             
                    Logic.Result(left.(input).success? ^ right.(input).success?, self, input)
         | 
| 72 84 | 
             
                  end
         | 
| 73 85 |  | 
| 74 | 
            -
                  def evaluate(input)
         | 
| 75 | 
            -
                    [left.evaluate(input), right.evaluate(input)]
         | 
| 76 | 
            -
                  end
         | 
| 77 | 
            -
             | 
| 78 86 | 
             
                  def type
         | 
| 79 87 | 
             
                    :xor
         | 
| 80 88 | 
             
                  end
         | 
    
        data/lib/dry/logic/rule/key.rb
    CHANGED
    
    | @@ -7,11 +7,12 @@ module Dry | |
| 7 7 |  | 
| 8 8 | 
             
                  def self.new(predicate, options)
         | 
| 9 9 | 
             
                    name = options.fetch(:name)
         | 
| 10 | 
            -
                     | 
| 10 | 
            +
                    eval = options.fetch(:evaluator, evaluator(name))
         | 
| 11 | 
            +
                    super(predicate, evaluator: eval, name: name)
         | 
| 11 12 | 
             
                  end
         | 
| 12 13 |  | 
| 13 | 
            -
                  def self.evaluator( | 
| 14 | 
            -
                    Evaluator::Key.new( | 
| 14 | 
            +
                  def self.evaluator(name)
         | 
| 15 | 
            +
                    Evaluator::Key.new(name)
         | 
| 15 16 | 
             
                  end
         | 
| 16 17 |  | 
| 17 18 | 
             
                  def initialize(predicate, options)
         | 
    
        data/lib/dry/logic/rule/set.rb
    CHANGED
    
    | @@ -7,10 +7,18 @@ module Dry | |
| 7 7 | 
             
                    :set
         | 
| 8 8 | 
             
                  end
         | 
| 9 9 |  | 
| 10 | 
            +
                  def arity
         | 
| 11 | 
            +
                    -1
         | 
| 12 | 
            +
                  end
         | 
| 13 | 
            +
             | 
| 10 14 | 
             
                  def apply(input)
         | 
| 11 15 | 
             
                    rules.map { |rule| rule.(input) }
         | 
| 12 16 | 
             
                  end
         | 
| 13 17 |  | 
| 18 | 
            +
                  def curry(*args)
         | 
| 19 | 
            +
                    new(rules.map { |r| r.curry(*args) })
         | 
| 20 | 
            +
                  end
         | 
| 21 | 
            +
             | 
| 14 22 | 
             
                  def at(*args)
         | 
| 15 23 | 
             
                    new(rules.values_at(*args))
         | 
| 16 24 | 
             
                  end
         | 
    
        data/lib/dry/logic/rule/value.rb
    CHANGED
    
    | @@ -5,12 +5,35 @@ module Dry | |
| 5 5 | 
             
                    :val
         | 
| 6 6 | 
             
                  end
         | 
| 7 7 |  | 
| 8 | 
            +
                  def nulary?
         | 
| 9 | 
            +
                    arity == 0
         | 
| 10 | 
            +
                  end
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                  def arity
         | 
| 13 | 
            +
                    @arity ||= predicate.arity
         | 
| 14 | 
            +
                  end
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                  def args
         | 
| 17 | 
            +
                    @args ||= predicate.args
         | 
| 18 | 
            +
                  end
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                  def input
         | 
| 21 | 
            +
                    predicate.args.last
         | 
| 22 | 
            +
                  end
         | 
| 23 | 
            +
             | 
| 8 24 | 
             
                  def call(input)
         | 
| 9 | 
            -
                     | 
| 25 | 
            +
                    if nulary?
         | 
| 26 | 
            +
                      Logic.Result(predicate.(), self, input)
         | 
| 27 | 
            +
                    else
         | 
| 28 | 
            +
                      evaled = evaluate(input)
         | 
| 29 | 
            +
                      result = apply(evaled)
         | 
| 30 | 
            +
                      rule = result == true ? self : curry(evaled)
         | 
| 31 | 
            +
                      Logic.Result(result, rule, input)
         | 
| 32 | 
            +
                    end
         | 
| 10 33 | 
             
                  end
         | 
| 11 34 |  | 
| 12 35 | 
             
                  def apply(input)
         | 
| 13 | 
            -
                    predicate.( | 
| 36 | 
            +
                    predicate.(input)
         | 
| 14 37 | 
             
                  end
         | 
| 15 38 |  | 
| 16 39 | 
             
                  def evaluate(input)
         | 
| @@ -50,8 +50,15 @@ module Dry | |
| 50 50 | 
             
                  end
         | 
| 51 51 |  | 
| 52 52 | 
             
                  def visit_predicate(node)
         | 
| 53 | 
            -
                    name,  | 
| 54 | 
            -
                    predicates[name] | 
| 53 | 
            +
                    name, params = node
         | 
| 54 | 
            +
                    predicate = predicates[name]
         | 
| 55 | 
            +
             | 
| 56 | 
            +
                    if params.size > 1
         | 
| 57 | 
            +
                      args = params.map(&:last).reject { |val| val == Predicate::Undefined }
         | 
| 58 | 
            +
                      predicate.curry(*args)
         | 
| 59 | 
            +
                    else
         | 
| 60 | 
            +
                      predicate
         | 
| 61 | 
            +
                    end
         | 
| 55 62 | 
             
                  end
         | 
| 56 63 |  | 
| 57 64 | 
             
                  def visit_and(node)
         | 
    
        data/lib/dry/logic/version.rb
    CHANGED
    
    
    
        data/spec/shared/predicates.rb
    CHANGED
    
    | @@ -30,8 +30,8 @@ RSpec.shared_examples 'a passing predicate' do | |
| 30 30 | 
             
              let(:predicate) { Dry::Logic::Predicates[predicate_name] }
         | 
| 31 31 |  | 
| 32 32 | 
             
              it do
         | 
| 33 | 
            -
                arguments_list.each do | | 
| 34 | 
            -
                  expect(predicate.call( | 
| 33 | 
            +
                arguments_list.each do |args|
         | 
| 34 | 
            +
                  expect(predicate.call(*args)).to be(true)
         | 
| 35 35 | 
             
                end
         | 
| 36 36 | 
             
              end
         | 
| 37 37 | 
             
            end
         | 
| @@ -40,8 +40,8 @@ RSpec.shared_examples 'a failing predicate' do | |
| 40 40 | 
             
              let(:predicate) { Dry::Logic::Predicates[predicate_name] }
         | 
| 41 41 |  | 
| 42 42 | 
             
              it do
         | 
| 43 | 
            -
                arguments_list.each do | | 
| 44 | 
            -
                  expect(predicate.call( | 
| 43 | 
            +
                arguments_list.each do |args|
         | 
| 44 | 
            +
                  expect(predicate.call(*args)).to be(false)
         | 
| 45 45 | 
             
                end
         | 
| 46 46 | 
             
              end
         | 
| 47 47 | 
             
            end
         | 
    
        data/spec/unit/predicate_spec.rb
    CHANGED
    
    | @@ -1,6 +1,35 @@ | |
| 1 1 | 
             
            require 'dry/logic/predicate'
         | 
| 2 2 |  | 
| 3 | 
            -
            RSpec.describe  | 
| 3 | 
            +
            RSpec.describe Predicate do
         | 
| 4 | 
            +
              describe '.new' do
         | 
| 5 | 
            +
                it 'can be initialized with empty args' do
         | 
| 6 | 
            +
                  predicate = Predicate.new(:id) { |v| v.is_a?(Integer) }
         | 
| 7 | 
            +
             | 
| 8 | 
            +
                  expect(predicate.to_ast).to eql([:predicate, [:id, [[:v, Predicate::Undefined]]]])
         | 
| 9 | 
            +
                end
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                it 'can be initialized with args' do
         | 
| 12 | 
            +
                  predicate = Predicate.new(:id, args: [1]) { |v| v.is_a?(Integer) }
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                  expect(predicate.to_ast).to eql([:predicate, [:id, [[:v, 1]]]])
         | 
| 15 | 
            +
                end
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                it 'can be initialized with fn as the last arg' do
         | 
| 18 | 
            +
                  predicate = Predicate.new(:id, args: [1], fn: -> v { v.is_a?(Integer) })
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                  expect(predicate.to_ast).to eql([:predicate, [:id, [[:v, 1]]]])
         | 
| 21 | 
            +
                end
         | 
| 22 | 
            +
              end
         | 
| 23 | 
            +
             | 
| 24 | 
            +
              describe '#bind' do
         | 
| 25 | 
            +
                it 'returns a predicate bound to a specific object' do
         | 
| 26 | 
            +
                  fn = String.instance_method(:empty?)
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                  expect(Dry::Logic.Predicate(fn).bind("").()).to be(true)
         | 
| 29 | 
            +
                  expect(Dry::Logic.Predicate(fn).bind("foo").()).to be(false)
         | 
| 30 | 
            +
                end
         | 
| 31 | 
            +
              end
         | 
| 32 | 
            +
             | 
| 4 33 | 
             
              describe '#call' do
         | 
| 5 34 | 
             
                it 'returns result of the predicate function' do
         | 
| 6 35 | 
             
                  is_empty = Dry::Logic::Predicate.new(:is_empty) { |str| str.empty? }
         | 
| @@ -9,6 +38,52 @@ RSpec.describe Dry::Logic::Predicate do | |
| 9 38 |  | 
| 10 39 | 
             
                  expect(is_empty.('filled')).to be(false)
         | 
| 11 40 | 
             
                end
         | 
| 41 | 
            +
             | 
| 42 | 
            +
                it "raises argument error when incorrect number of args provided" do
         | 
| 43 | 
            +
                  min_age = Dry::Logic::Predicate.new(:min_age) { |age, input| input >= age }
         | 
| 44 | 
            +
             | 
| 45 | 
            +
                  expect { min_age.curry(10, 12, 14) }.to raise_error(ArgumentError)
         | 
| 46 | 
            +
                  expect { min_age.(18, 19, 20, 30) }.to raise_error(ArgumentError)
         | 
| 47 | 
            +
                  expect { min_age.curry(18).(19, 20) }.to raise_error(ArgumentError)
         | 
| 48 | 
            +
                end
         | 
| 49 | 
            +
             | 
| 50 | 
            +
                it "predicates should work without any args" do
         | 
| 51 | 
            +
                  is_empty = Dry::Logic::Predicate.new(:is_empty) { true }
         | 
| 52 | 
            +
             | 
| 53 | 
            +
                  expect(is_empty.()).to be(true)
         | 
| 54 | 
            +
                end
         | 
| 55 | 
            +
              end
         | 
| 56 | 
            +
             | 
| 57 | 
            +
              describe '#arity' do
         | 
| 58 | 
            +
                it 'returns arity of the predicate function' do
         | 
| 59 | 
            +
                  is_equal = Dry::Logic::Predicate.new(:is_equal) { |left, right| left == right }
         | 
| 60 | 
            +
             | 
| 61 | 
            +
                  expect(is_equal.arity).to eql(2)
         | 
| 62 | 
            +
                end
         | 
| 63 | 
            +
              end
         | 
| 64 | 
            +
             | 
| 65 | 
            +
              describe '#parameters' do
         | 
| 66 | 
            +
                it 'returns arity of the predicate function' do
         | 
| 67 | 
            +
                  is_equal = Dry::Logic::Predicate.new(:is_equal) { |left, right| left == right }
         | 
| 68 | 
            +
             | 
| 69 | 
            +
                  expect(is_equal.parameters).to eql([[:opt, :left], [:opt, :right]])
         | 
| 70 | 
            +
                end
         | 
| 71 | 
            +
              end
         | 
| 72 | 
            +
             | 
| 73 | 
            +
              describe '#arity' do
         | 
| 74 | 
            +
                it 'returns arity of the predicate function' do
         | 
| 75 | 
            +
                  is_equal = Dry::Logic::Predicate.new(:is_equal) { |left, right| left == right }
         | 
| 76 | 
            +
             | 
| 77 | 
            +
                  expect(is_equal.arity).to eql(2)
         | 
| 78 | 
            +
                end
         | 
| 79 | 
            +
              end
         | 
| 80 | 
            +
             | 
| 81 | 
            +
              describe '#parameters' do
         | 
| 82 | 
            +
                it 'returns arity of the predicate function' do
         | 
| 83 | 
            +
                  is_equal = Dry::Logic::Predicate.new(:is_equal) { |left, right| left == right }
         | 
| 84 | 
            +
             | 
| 85 | 
            +
                  expect(is_equal.parameters).to eql([[:opt, :left], [:opt, :right]])
         | 
| 86 | 
            +
                end
         | 
| 12 87 | 
             
              end
         | 
| 13 88 |  | 
| 14 89 | 
             
              describe '#curry' do
         | 
| @@ -23,5 +98,18 @@ RSpec.describe Dry::Logic::Predicate do | |
| 23 98 | 
             
                  expect(min_age_18.(19)).to be(true)
         | 
| 24 99 | 
             
                  expect(min_age_18.(17)).to be(false)
         | 
| 25 100 | 
             
                end
         | 
| 101 | 
            +
             | 
| 102 | 
            +
                it 'can curry again & again' do
         | 
| 103 | 
            +
                  min_age = Dry::Logic::Predicate.new(:min_age) { |age, input| input >= age }
         | 
| 104 | 
            +
             | 
| 105 | 
            +
                  min_age_18 = min_age.curry(18)
         | 
| 106 | 
            +
             | 
| 107 | 
            +
                  expect(min_age_18.args).to eql([18])
         | 
| 108 | 
            +
             | 
| 109 | 
            +
                  actual_age_19 = min_age_18.curry(19)
         | 
| 110 | 
            +
             | 
| 111 | 
            +
                  expect(actual_age_19.()).to be(true)
         | 
| 112 | 
            +
                  expect(actual_age_19.args).to eql([18,19])
         | 
| 113 | 
            +
                end
         | 
| 26 114 | 
             
              end
         | 
| 27 115 | 
             
            end
         | 
| @@ -0,0 +1,41 @@ | |
| 1 | 
            +
            require 'dry/logic/predicates'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            RSpec.describe Dry::Logic::Predicates do
         | 
| 4 | 
            +
              describe '#array?' do
         | 
| 5 | 
            +
                let(:predicate_name) { :array? }
         | 
| 6 | 
            +
             | 
| 7 | 
            +
                context 'when value is an array' do
         | 
| 8 | 
            +
                  let(:arguments_list) do
         | 
| 9 | 
            +
                    [
         | 
| 10 | 
            +
                      [ [] ],
         | 
| 11 | 
            +
                      [ ['other', 'array'] ],
         | 
| 12 | 
            +
                      [ [123, 'really', :blah] ],
         | 
| 13 | 
            +
                      [ Array.new ],
         | 
| 14 | 
            +
                      [ [nil] ],
         | 
| 15 | 
            +
                      [ [false] ],
         | 
| 16 | 
            +
                      [ [true] ]
         | 
| 17 | 
            +
                    ]
         | 
| 18 | 
            +
                  end
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                  it_behaves_like 'a passing predicate'
         | 
| 21 | 
            +
                end
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                context 'when value is not an array' do
         | 
| 24 | 
            +
                  let(:arguments_list) do
         | 
| 25 | 
            +
                    [
         | 
| 26 | 
            +
                      [''],
         | 
| 27 | 
            +
                      [{}],
         | 
| 28 | 
            +
                      [nil],
         | 
| 29 | 
            +
                      [:symbol],
         | 
| 30 | 
            +
                      [String],
         | 
| 31 | 
            +
                      [1],
         | 
| 32 | 
            +
                      [1.0],
         | 
| 33 | 
            +
                      [true],
         | 
| 34 | 
            +
                      [Hash.new]
         | 
| 35 | 
            +
                    ]
         | 
| 36 | 
            +
                  end
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                  it_behaves_like 'a failing predicate'
         | 
| 39 | 
            +
                end
         | 
| 40 | 
            +
              end
         | 
| 41 | 
            +
            end
         | 
| @@ -0,0 +1,35 @@ | |
| 1 | 
            +
            require 'dry/logic/predicates'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            RSpec.describe Dry::Logic::Predicates do
         | 
| 4 | 
            +
              describe '#type?' do
         | 
| 5 | 
            +
                let(:predicate_name) { :type? }
         | 
| 6 | 
            +
             | 
| 7 | 
            +
                context 'when value has a correct type' do
         | 
| 8 | 
            +
                  let(:arguments_list) do
         | 
| 9 | 
            +
                    [[TrueClass, true]]
         | 
| 10 | 
            +
                  end
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                  it_behaves_like 'a passing predicate'
         | 
| 13 | 
            +
                end
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                context 'with value is not true' do
         | 
| 16 | 
            +
                  let(:arguments_list) do
         | 
| 17 | 
            +
                    [
         | 
| 18 | 
            +
                      [TrueClass, false],
         | 
| 19 | 
            +
                      [TrueClass, ''],
         | 
| 20 | 
            +
                      [TrueClass, []],
         | 
| 21 | 
            +
                      [TrueClass, {}],
         | 
| 22 | 
            +
                      [TrueClass, nil],
         | 
| 23 | 
            +
                      [TrueClass, :symbol],
         | 
| 24 | 
            +
                      [TrueClass, String],
         | 
| 25 | 
            +
                      [TrueClass, 1],
         | 
| 26 | 
            +
                      [TrueClass, 0],
         | 
| 27 | 
            +
                      [TrueClass, 'true'],
         | 
| 28 | 
            +
                      [TrueClass, 'false']
         | 
| 29 | 
            +
                    ]
         | 
| 30 | 
            +
                  end
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                  it_behaves_like 'a failing predicate'
         | 
| 33 | 
            +
                end
         | 
| 34 | 
            +
              end
         | 
| 35 | 
            +
            end
         | 
| @@ -13,7 +13,7 @@ RSpec.describe Rule::Check do | |
| 13 13 |  | 
| 14 14 | 
             
                    expect(rule.(num: 1).to_ast).to eql(
         | 
| 15 15 | 
             
                      [:input, [:compare, [
         | 
| 16 | 
            -
                        :result, [1, [:check, [:compare, [:predicate, [:eql?, [1]]]]]]]]
         | 
| 16 | 
            +
                        :result, [1, [:check, [:compare, [:predicate, [:eql?, [[:left, 1], [:right, 1]]]]]]]]]
         | 
| 17 17 | 
             
                      ]
         | 
| 18 18 | 
             
                    )
         | 
| 19 19 | 
             
                  end
         | 
| @@ -29,12 +29,13 @@ RSpec.describe Rule::Check do | |
| 29 29 | 
             
                    expect(rule.(nums: { left: 1, right: 2 })).to be_failure
         | 
| 30 30 | 
             
                  end
         | 
| 31 31 |  | 
| 32 | 
            +
                  #check rules reverse the order of params to enable cases like `left.gt(right)` to work
         | 
| 32 33 | 
             
                  it 'curries args properly' do
         | 
| 33 34 | 
             
                    result = rule.(nums: { left: 1, right: 2 })
         | 
| 34 35 |  | 
| 35 36 | 
             
                    expect(result.to_ast).to eql([
         | 
| 36 37 | 
             
                      :input, [:compare, [
         | 
| 37 | 
            -
                        :result, [1, [:check, [:compare, [:predicate, [:eql?, [2]]]]]]]
         | 
| 38 | 
            +
                        :result, [1, [:check, [:compare, [:predicate, [:eql?, [[:left, 2], [:right, 1]]]]]]]]
         | 
| 38 39 | 
             
                      ]
         | 
| 39 40 | 
             
                    ])
         | 
| 40 41 | 
             
                  end
         | 
    
        data/spec/unit/rule/each_spec.rb
    CHANGED
    
    | @@ -21,8 +21,8 @@ RSpec.describe Dry::Logic::Rule::Each do | |
| 21 21 | 
             
                  expect(address_rule.([nil, nil]).to_ast).to eql([
         | 
| 22 22 | 
             
                    :result, [[nil, nil], [
         | 
| 23 23 | 
             
                      :each, [
         | 
| 24 | 
            -
                        [:el, [0, [:result, [nil, [:val, [:predicate, [:str?, []]]]]]]],
         | 
| 25 | 
            -
                        [:el, [1, [:result, [nil, [:val, [:predicate, [:str?, []]]]]]]]
         | 
| 24 | 
            +
                        [:el, [0, [:result, [nil, [:val, [:predicate, [:str?, [[:input, nil]]]]]]]]],
         | 
| 25 | 
            +
                        [:el, [1, [:result, [nil, [:val, [:predicate, [:str?, [[:input, nil]]]]]]]]]
         | 
| 26 26 | 
             
                      ]
         | 
| 27 27 | 
             
                    ]]
         | 
| 28 28 | 
             
                  ])
         | 
    
        data/spec/unit/rule/key_spec.rb
    CHANGED
    
    | @@ -56,7 +56,7 @@ RSpec.describe Rule::Key do | |
| 56 56 | 
             
                        :address,
         | 
| 57 57 | 
             
                          [:result, [
         | 
| 58 58 | 
             
                            { city: "NYC" },
         | 
| 59 | 
            -
                            [:set, [[:result, [{ city: 'NYC' }, [:val, [:predicate, [:key?, [:zipcode]]]]]]]]
         | 
| 59 | 
            +
                            [:set, [[:result, [{ city: 'NYC' }, [:val, [:predicate, [:key?, [[:name, :zipcode], [:input, {:city=>"NYC"}]]]]]]]]]
         | 
| 60 60 | 
             
                          ]]
         | 
| 61 61 | 
             
                        ]
         | 
| 62 62 | 
             
                    ])
         | 
| @@ -93,8 +93,8 @@ RSpec.describe Rule::Key do | |
| 93 93 | 
             
                          :result, [
         | 
| 94 94 | 
             
                            [1, '3', 3],
         | 
| 95 95 | 
             
                            [:each, [
         | 
| 96 | 
            -
                              [:el, [0, [:result, [1, [:val, [:predicate, [:str?, []]]]]]]],
         | 
| 97 | 
            -
                              [:el, [2, [:result, [3, [:val, [:predicate, [:str?, []]]]]]]]
         | 
| 96 | 
            +
                              [:el, [0, [:result, [1, [:val, [:predicate, [:str?, [[:input, 1]]]]]]]]],
         | 
| 97 | 
            +
                              [:el, [2, [:result, [3, [:val, [:predicate, [:str?, [[:input, 3]]]]]]]]]
         | 
| 98 98 | 
             
                            ]]
         | 
| 99 99 | 
             
                          ]
         | 
| 100 100 | 
             
                        ]
         | 
    
        data/spec/unit/rule/set_spec.rb
    CHANGED
    
    | @@ -21,8 +21,8 @@ RSpec.describe Dry::Logic::Rule::Set do | |
| 21 21 | 
             
                it 'returns an array representation' do
         | 
| 22 22 | 
             
                  expect(rule.to_ast).to eql([
         | 
| 23 23 | 
             
                    :set, [
         | 
| 24 | 
            -
                      [:val, [:predicate, [:str?, []]]],
         | 
| 25 | 
            -
                      [:val, [:predicate, [:min_size?, [6]]]]
         | 
| 24 | 
            +
                      [:val, [:predicate, [:str?, [[:input, Predicate::Undefined]]]]],
         | 
| 25 | 
            +
                      [:val, [:predicate, [:min_size?, [[:num, 6], [:input, Predicate::Undefined]]]]]
         | 
| 26 26 | 
             
                    ]
         | 
| 27 27 | 
             
                  ])
         | 
| 28 28 | 
             
                end
         | 
| @@ -15,11 +15,31 @@ RSpec.describe Dry::Logic::Rule::Value do | |
| 15 15 | 
             
                  expect(is_string.('1')).to be_success
         | 
| 16 16 | 
             
                end
         | 
| 17 17 |  | 
| 18 | 
            +
                context 'with a composite rule' do
         | 
| 19 | 
            +
                  subject(:rule) { Dry::Logic::Rule::Value.new(is_nil | is_string) }
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                  it 'returns a success for valid input' do
         | 
| 22 | 
            +
                    expect(rule.(nil)).to be_success
         | 
| 23 | 
            +
                    expect(rule.('foo')).to be_success
         | 
| 24 | 
            +
                  end
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                  it 'returns a failure for invalid input' do
         | 
| 27 | 
            +
                    expect(rule.(312)).to be_failure
         | 
| 28 | 
            +
                  end
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                  it 'returns a failure result with curried args' do
         | 
| 31 | 
            +
                    expect(rule.(312).to_ast).to eql(
         | 
| 32 | 
            +
                      [:result, [312, [:val, [:predicate, [:str?, [[:input, 312]]]]]]]
         | 
| 33 | 
            +
                    )
         | 
| 34 | 
            +
                  end
         | 
| 35 | 
            +
                end
         | 
| 36 | 
            +
             | 
| 18 37 | 
             
                context 'with a custom predicate' do
         | 
| 19 38 | 
             
                  subject(:rule) { Dry::Logic::Rule::Value.new(predicate) }
         | 
| 20 39 |  | 
| 21 | 
            -
                  let(:response) { double(success?: true) }
         | 
| 22 | 
            -
                  let(:predicate) {  | 
| 40 | 
            +
                  let(:response) { double("response", success?: true) }
         | 
| 41 | 
            +
                  let(:predicate) { double("predicate", arity: 1, curry: curried, call: Result.new(response, double("rule"), test: true)) }
         | 
| 42 | 
            +
                  let(:curried) { double("curried", arity: 1, call: Result.new(response, double("rule"), test: true)) }
         | 
| 23 43 |  | 
| 24 44 | 
             
                  let(:result) { rule.(test: true) }
         | 
| 25 45 |  | 
| @@ -39,6 +59,17 @@ RSpec.describe Dry::Logic::Rule::Value do | |
| 39 59 | 
             
                  it 'has no name by default' do
         | 
| 40 60 | 
             
                    expect(result.name).to be(nil)
         | 
| 41 61 | 
             
                  end
         | 
| 62 | 
            +
             | 
| 63 | 
            +
                  context "works with predicates.arity == 0" do
         | 
| 64 | 
            +
                    subject(:rule) { Dry::Logic::Rule::Value.new(predicate) }
         | 
| 65 | 
            +
             | 
| 66 | 
            +
                    let(:predicate) { Dry::Logic::Predicate.new(:without_args) { true } }
         | 
| 67 | 
            +
                    let(:result) { rule.('sutin') }
         | 
| 68 | 
            +
             | 
| 69 | 
            +
                    it "calls its predicate without any args" do
         | 
| 70 | 
            +
                      expect(result).to be_success
         | 
| 71 | 
            +
                    end
         | 
| 72 | 
            +
                  end
         | 
| 42 73 | 
             
                end
         | 
| 43 74 | 
             
              end
         | 
| 44 75 |  | 
| @@ -25,7 +25,7 @@ RSpec.describe Dry::Logic::RuleCompiler, '#call' do | |
| 25 25 | 
             
              let(:each_rule) { Rule::Each.new(val_rule) }
         | 
| 26 26 |  | 
| 27 27 | 
             
              it 'compiles key rules' do
         | 
| 28 | 
            -
                ast = [[:key, [:email, [:predicate, [:filled?, []]]]]]
         | 
| 28 | 
            +
                ast = [[:key, [:email, [:predicate, [:filled?, [[:input, nil]]]]]]]
         | 
| 29 29 |  | 
| 30 30 | 
             
                rules = compiler.(ast)
         | 
| 31 31 |  | 
| @@ -33,7 +33,7 @@ RSpec.describe Dry::Logic::RuleCompiler, '#call' do | |
| 33 33 | 
             
              end
         | 
| 34 34 |  | 
| 35 35 | 
             
              it 'compiles attr rules' do
         | 
| 36 | 
            -
                ast = [[:attr, [:email, [:predicate, [:filled?, []]]]]]
         | 
| 36 | 
            +
                ast = [[:attr, [:email, [:predicate, [:filled?, [[:input, nil]]]]]]]
         | 
| 37 37 |  | 
| 38 38 | 
             
                rules = compiler.(ast)
         | 
| 39 39 |  | 
| @@ -41,7 +41,7 @@ RSpec.describe Dry::Logic::RuleCompiler, '#call' do | |
| 41 41 | 
             
              end
         | 
| 42 42 |  | 
| 43 43 | 
             
              it 'compiles check rules' do
         | 
| 44 | 
            -
                ast = [[:check, [:email, [:predicate, [:filled?, []]]]]]
         | 
| 44 | 
            +
                ast = [[:check, [:email, [:predicate, [:filled?, [[:input, nil]]]]]]]
         | 
| 45 45 |  | 
| 46 46 | 
             
                rules = compiler.(ast)
         | 
| 47 47 |  | 
| @@ -49,7 +49,7 @@ RSpec.describe Dry::Logic::RuleCompiler, '#call' do | |
| 49 49 | 
             
              end
         | 
| 50 50 |  | 
| 51 51 | 
             
              it 'compiles attr rules' do
         | 
| 52 | 
            -
                ast = [[:attr, [:email, [:predicate, [:attr?,  | 
| 52 | 
            +
                ast = [[:attr, [:email, [:predicate, [:attr?, [[:name, :email]]]]]]]
         | 
| 53 53 |  | 
| 54 54 | 
             
                rules = compiler.(ast)
         | 
| 55 55 |  | 
| @@ -57,7 +57,7 @@ RSpec.describe Dry::Logic::RuleCompiler, '#call' do | |
| 57 57 | 
             
              end
         | 
| 58 58 |  | 
| 59 59 | 
             
              it 'compiles negated rules' do
         | 
| 60 | 
            -
                ast = [[:not, [:key, [:email, [:predicate, [:filled?, []]]]]]]
         | 
| 60 | 
            +
                ast = [[:not, [:key, [:email, [:predicate, [:filled?, [[:input, nil]]]]]]]]
         | 
| 61 61 |  | 
| 62 62 | 
             
                rules = compiler.(ast)
         | 
| 63 63 |  | 
| @@ -68,8 +68,8 @@ RSpec.describe Dry::Logic::RuleCompiler, '#call' do | |
| 68 68 | 
             
                ast = [
         | 
| 69 69 | 
             
                  [
         | 
| 70 70 | 
             
                    :and, [
         | 
| 71 | 
            -
                      [:key, [:email, [:predicate, [:key?, []]]]],
         | 
| 72 | 
            -
                      [:val, [:predicate, [:filled?, []]]]
         | 
| 71 | 
            +
                      [:key, [:email, [:predicate, [:key?, [[:name, :email], [:input, nil]]]]]],
         | 
| 72 | 
            +
                      [:val, [:predicate, [:filled?, [[:input, nil]]]]]
         | 
| 73 73 | 
             
                    ]
         | 
| 74 74 | 
             
                  ]
         | 
| 75 75 | 
             
                ]
         | 
| @@ -83,8 +83,8 @@ RSpec.describe Dry::Logic::RuleCompiler, '#call' do | |
| 83 83 | 
             
                ast = [
         | 
| 84 84 | 
             
                  [
         | 
| 85 85 | 
             
                    :or, [
         | 
| 86 | 
            -
                      [:key, [:email, [:predicate, [:key?, []]]]],
         | 
| 87 | 
            -
                      [:val, [:predicate, [:filled?, []]]]
         | 
| 86 | 
            +
                      [:key, [:email, [:predicate, [:key?, [[:name, :email], [:input, nil]]]]]],
         | 
| 87 | 
            +
                      [:val, [:predicate, [:filled?, [[:input, nil]]]]]
         | 
| 88 88 | 
             
                    ]
         | 
| 89 89 | 
             
                  ]
         | 
| 90 90 | 
             
                ]
         | 
| @@ -98,8 +98,8 @@ RSpec.describe Dry::Logic::RuleCompiler, '#call' do | |
| 98 98 | 
             
                ast = [
         | 
| 99 99 | 
             
                  [
         | 
| 100 100 | 
             
                    :xor, [
         | 
| 101 | 
            -
                      [:key, [:email, [:predicate, [:key?, []]]]],
         | 
| 102 | 
            -
                      [:val, [:predicate, [:filled?, []]]]
         | 
| 101 | 
            +
                      [:key, [:email, [:predicate, [:key?, [[:name, :email], [:input, nil]]]]]],
         | 
| 102 | 
            +
                      [:val, [:predicate, [:filled?, [[:input, nil]]]]]
         | 
| 103 103 | 
             
                    ]
         | 
| 104 104 | 
             
                  ]
         | 
| 105 105 | 
             
                ]
         | 
| @@ -110,7 +110,7 @@ RSpec.describe Dry::Logic::RuleCompiler, '#call' do | |
| 110 110 | 
             
              end
         | 
| 111 111 |  | 
| 112 112 | 
             
              it 'compiles set rules' do
         | 
| 113 | 
            -
                ast = [[:set, [[:val, [:predicate, [:filled?, []]]]]]]
         | 
| 113 | 
            +
                ast = [[:set, [[:val, [:predicate, [:filled?, [[:input, nil]]]]]]]]
         | 
| 114 114 |  | 
| 115 115 | 
             
                rules = compiler.(ast)
         | 
| 116 116 |  | 
| @@ -118,7 +118,7 @@ RSpec.describe Dry::Logic::RuleCompiler, '#call' do | |
| 118 118 | 
             
              end
         | 
| 119 119 |  | 
| 120 120 | 
             
              it 'compiles each rules' do
         | 
| 121 | 
            -
                ast = [[:each, [:val, [:predicate, [:filled?, []]]]]]
         | 
| 121 | 
            +
                ast = [[:each, [:val, [:predicate, [:filled?, [[:input, nil]]]]]]]
         | 
| 122 122 |  | 
| 123 123 | 
             
                rules = compiler.(ast)
         | 
| 124 124 |  | 
    
        metadata
    CHANGED
    
    | @@ -1,14 +1,14 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: dry-logic
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 0. | 
| 4 | 
            +
              version: 0.3.0
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Piotr Solnica
         | 
| 8 8 | 
             
            autorequire: 
         | 
| 9 9 | 
             
            bindir: bin
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date: 2016- | 
| 11 | 
            +
            date: 2016-07-01 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: dry-container
         | 
| @@ -131,6 +131,7 @@ files: | |
| 131 131 | 
             
            - spec/shared/predicates.rb
         | 
| 132 132 | 
             
            - spec/spec_helper.rb
         | 
| 133 133 | 
             
            - spec/unit/predicate_spec.rb
         | 
| 134 | 
            +
            - spec/unit/predicates/array_spec.rb
         | 
| 134 135 | 
             
            - spec/unit/predicates/attr_spec.rb
         | 
| 135 136 | 
             
            - spec/unit/predicates/bool_spec.rb
         | 
| 136 137 | 
             
            - spec/unit/predicates/date_spec.rb
         | 
| @@ -163,6 +164,7 @@ files: | |
| 163 164 | 
             
            - spec/unit/predicates/str_spec.rb
         | 
| 164 165 | 
             
            - spec/unit/predicates/time_spec.rb
         | 
| 165 166 | 
             
            - spec/unit/predicates/true_spec.rb
         | 
| 167 | 
            +
            - spec/unit/predicates/type_spec.rb
         | 
| 166 168 | 
             
            - spec/unit/rule/attr_spec.rb
         | 
| 167 169 | 
             
            - spec/unit/rule/check_spec.rb
         | 
| 168 170 | 
             
            - spec/unit/rule/conjunction_spec.rb
         | 
| @@ -194,7 +196,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement | |
| 194 196 | 
             
                  version: '0'
         | 
| 195 197 | 
             
            requirements: []
         | 
| 196 198 | 
             
            rubyforge_project: 
         | 
| 197 | 
            -
            rubygems_version: 2. | 
| 199 | 
            +
            rubygems_version: 2.5.1
         | 
| 198 200 | 
             
            signing_key: 
         | 
| 199 201 | 
             
            specification_version: 4
         | 
| 200 202 | 
             
            summary: Predicate logic with rule composition
         | 
| @@ -202,6 +204,7 @@ test_files: | |
| 202 204 | 
             
            - spec/shared/predicates.rb
         | 
| 203 205 | 
             
            - spec/spec_helper.rb
         | 
| 204 206 | 
             
            - spec/unit/predicate_spec.rb
         | 
| 207 | 
            +
            - spec/unit/predicates/array_spec.rb
         | 
| 205 208 | 
             
            - spec/unit/predicates/attr_spec.rb
         | 
| 206 209 | 
             
            - spec/unit/predicates/bool_spec.rb
         | 
| 207 210 | 
             
            - spec/unit/predicates/date_spec.rb
         | 
| @@ -234,6 +237,7 @@ test_files: | |
| 234 237 | 
             
            - spec/unit/predicates/str_spec.rb
         | 
| 235 238 | 
             
            - spec/unit/predicates/time_spec.rb
         | 
| 236 239 | 
             
            - spec/unit/predicates/true_spec.rb
         | 
| 240 | 
            +
            - spec/unit/predicates/type_spec.rb
         | 
| 237 241 | 
             
            - spec/unit/rule/attr_spec.rb
         | 
| 238 242 | 
             
            - spec/unit/rule/check_spec.rb
         | 
| 239 243 | 
             
            - spec/unit/rule/conjunction_spec.rb
         | 
| @@ -245,3 +249,4 @@ test_files: | |
| 245 249 | 
             
            - spec/unit/rule/set_spec.rb
         | 
| 246 250 | 
             
            - spec/unit/rule/value_spec.rb
         | 
| 247 251 | 
             
            - spec/unit/rule_compiler_spec.rb
         | 
| 252 | 
            +
            has_rdoc: 
         |