dry-logic 1.0.5 → 1.1.1

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.
Files changed (113) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +122 -26
  3. data/LICENSE +1 -1
  4. data/README.md +12 -14
  5. data/dry-logic.gemspec +26 -20
  6. data/lib/dry-logic.rb +1 -1
  7. data/lib/dry/logic.rb +2 -2
  8. data/lib/dry/logic/evaluator.rb +1 -1
  9. data/lib/dry/logic/operations.rb +11 -11
  10. data/lib/dry/logic/operations/abstract.rb +3 -3
  11. data/lib/dry/logic/operations/and.rb +3 -3
  12. data/lib/dry/logic/operations/attr.rb +1 -1
  13. data/lib/dry/logic/operations/binary.rb +4 -3
  14. data/lib/dry/logic/operations/check.rb +4 -4
  15. data/lib/dry/logic/operations/each.rb +2 -2
  16. data/lib/dry/logic/operations/implication.rb +2 -2
  17. data/lib/dry/logic/operations/key.rb +3 -3
  18. data/lib/dry/logic/operations/negation.rb +2 -2
  19. data/lib/dry/logic/operations/or.rb +2 -2
  20. data/lib/dry/logic/operations/set.rb +3 -3
  21. data/lib/dry/logic/operations/unary.rb +1 -1
  22. data/lib/dry/logic/operations/xor.rb +2 -2
  23. data/lib/dry/logic/operators.rb +4 -4
  24. data/lib/dry/logic/predicates.rb +32 -7
  25. data/lib/dry/logic/result.rb +2 -2
  26. data/lib/dry/logic/rule.rb +8 -8
  27. data/lib/dry/logic/rule/interface.rb +32 -37
  28. data/lib/dry/logic/rule/predicate.rb +3 -3
  29. data/lib/dry/logic/rule_compiler.rb +3 -3
  30. data/lib/dry/logic/version.rb +1 -1
  31. metadata +17 -166
  32. data/.codeclimate.yml +0 -12
  33. data/.github/ISSUE_TEMPLATE/----please-don-t-ask-for-support-via-issues.md +0 -10
  34. data/.github/ISSUE_TEMPLATE/---bug-report.md +0 -34
  35. data/.github/ISSUE_TEMPLATE/---feature-request.md +0 -18
  36. data/.github/workflows/ci.yml +0 -70
  37. data/.github/workflows/docsite.yml +0 -34
  38. data/.github/workflows/sync_configs.yml +0 -34
  39. data/.gitignore +0 -9
  40. data/.rspec +0 -4
  41. data/.rubocop.yml +0 -89
  42. data/CODE_OF_CONDUCT.md +0 -13
  43. data/CONTRIBUTING.md +0 -29
  44. data/Gemfile +0 -16
  45. data/Rakefile +0 -14
  46. data/benchmarks/rule_application.rb +0 -30
  47. data/benchmarks/setup.rb +0 -13
  48. data/bin/console +0 -11
  49. data/docsite/source/index.html.md +0 -54
  50. data/docsite/source/operations.html.md +0 -62
  51. data/docsite/source/predicates.html.md +0 -102
  52. data/examples/basic.rb +0 -16
  53. data/spec/integration/result_spec.rb +0 -61
  54. data/spec/integration/rule_spec.rb +0 -55
  55. data/spec/shared/predicates.rb +0 -59
  56. data/spec/shared/rule.rb +0 -74
  57. data/spec/spec_helper.rb +0 -30
  58. data/spec/support/mutant.rb +0 -11
  59. data/spec/unit/operations/and_spec.rb +0 -70
  60. data/spec/unit/operations/attr_spec.rb +0 -29
  61. data/spec/unit/operations/check_spec.rb +0 -51
  62. data/spec/unit/operations/each_spec.rb +0 -49
  63. data/spec/unit/operations/implication_spec.rb +0 -32
  64. data/spec/unit/operations/key_spec.rb +0 -135
  65. data/spec/unit/operations/negation_spec.rb +0 -51
  66. data/spec/unit/operations/or_spec.rb +0 -75
  67. data/spec/unit/operations/set_spec.rb +0 -43
  68. data/spec/unit/operations/xor_spec.rb +0 -63
  69. data/spec/unit/predicates/array_spec.rb +0 -43
  70. data/spec/unit/predicates/attr_spec.rb +0 -31
  71. data/spec/unit/predicates/bool_spec.rb +0 -36
  72. data/spec/unit/predicates/bytesize_spec.rb +0 -48
  73. data/spec/unit/predicates/case_spec.rb +0 -35
  74. data/spec/unit/predicates/date_spec.rb +0 -33
  75. data/spec/unit/predicates/date_time_spec.rb +0 -33
  76. data/spec/unit/predicates/decimal_spec.rb +0 -34
  77. data/spec/unit/predicates/empty_spec.rb +0 -40
  78. data/spec/unit/predicates/eql_spec.rb +0 -23
  79. data/spec/unit/predicates/even_spec.rb +0 -33
  80. data/spec/unit/predicates/excluded_from_spec.rb +0 -37
  81. data/spec/unit/predicates/excludes_spec.rb +0 -58
  82. data/spec/unit/predicates/false_spec.rb +0 -37
  83. data/spec/unit/predicates/filled_spec.rb +0 -40
  84. data/spec/unit/predicates/float_spec.rb +0 -33
  85. data/spec/unit/predicates/format_spec.rb +0 -31
  86. data/spec/unit/predicates/gt_spec.rb +0 -42
  87. data/spec/unit/predicates/gteq_spec.rb +0 -42
  88. data/spec/unit/predicates/hash_spec.rb +0 -40
  89. data/spec/unit/predicates/included_in_spec.rb +0 -37
  90. data/spec/unit/predicates/includes_spec.rb +0 -24
  91. data/spec/unit/predicates/int_spec.rb +0 -36
  92. data/spec/unit/predicates/key_spec.rb +0 -31
  93. data/spec/unit/predicates/lt_spec.rb +0 -42
  94. data/spec/unit/predicates/lteq_spec.rb +0 -42
  95. data/spec/unit/predicates/max_bytesize_spec.rb +0 -39
  96. data/spec/unit/predicates/max_size_spec.rb +0 -51
  97. data/spec/unit/predicates/min_bytesize_spec.rb +0 -39
  98. data/spec/unit/predicates/min_size_spec.rb +0 -51
  99. data/spec/unit/predicates/none_spec.rb +0 -30
  100. data/spec/unit/predicates/not_eql_spec.rb +0 -23
  101. data/spec/unit/predicates/number_spec.rb +0 -39
  102. data/spec/unit/predicates/odd_spec.rb +0 -33
  103. data/spec/unit/predicates/respond_to_spec.rb +0 -31
  104. data/spec/unit/predicates/size_spec.rb +0 -57
  105. data/spec/unit/predicates/str_spec.rb +0 -34
  106. data/spec/unit/predicates/time_spec.rb +0 -33
  107. data/spec/unit/predicates/true_spec.rb +0 -37
  108. data/spec/unit/predicates/type_spec.rb +0 -37
  109. data/spec/unit/predicates/uuid_v4_spec.rb +0 -29
  110. data/spec/unit/predicates_spec.rb +0 -25
  111. data/spec/unit/rule/predicate_spec.rb +0 -55
  112. data/spec/unit/rule_compiler_spec.rb +0 -129
  113. data/spec/unit/rule_spec.rb +0 -213
@@ -1,34 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'dry/logic/predicates'
4
-
5
- RSpec.describe Dry::Logic::Predicates do
6
- describe '#str?' do
7
- let(:predicate_name) { :str? }
8
-
9
- context 'when value is a string' do
10
- let(:arguments_list) do
11
- [
12
- [''],
13
- ['John']
14
- ]
15
- end
16
-
17
- it_behaves_like 'a passing predicate'
18
- end
19
-
20
- context 'with value is not a string' do
21
- let(:arguments_list) do
22
- [
23
- [[]],
24
- [{}],
25
- [nil],
26
- [:symbol],
27
- [String]
28
- ]
29
- end
30
-
31
- it_behaves_like 'a failing predicate'
32
- end
33
- end
34
- end
@@ -1,33 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'dry/logic/predicates'
4
-
5
- RSpec.describe Dry::Logic::Predicates do
6
- describe '#time?' do
7
- let(:predicate_name) { :time? }
8
-
9
- context 'when value is a time' do
10
- let(:arguments_list) do
11
- [[Time.now]]
12
- end
13
-
14
- it_behaves_like 'a passing predicate'
15
- end
16
-
17
- context 'with value is not an integer' do
18
- let(:arguments_list) do
19
- [
20
- [''],
21
- [[]],
22
- [{}],
23
- [nil],
24
- [:symbol],
25
- [String],
26
- [1]
27
- ]
28
- end
29
-
30
- it_behaves_like 'a failing predicate'
31
- end
32
- end
33
- end
@@ -1,37 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'dry/logic/predicates'
4
-
5
- RSpec.describe Dry::Logic::Predicates do
6
- describe '#true?' do
7
- let(:predicate_name) { :true? }
8
-
9
- context 'when value is true' do
10
- let(:arguments_list) do
11
- [[true]]
12
- end
13
-
14
- it_behaves_like 'a passing predicate'
15
- end
16
-
17
- context 'with value is not true' do
18
- let(:arguments_list) do
19
- [
20
- [false],
21
- [''],
22
- [[]],
23
- [{}],
24
- [nil],
25
- [:symbol],
26
- [String],
27
- [1],
28
- [0],
29
- ['true'],
30
- ['false']
31
- ]
32
- end
33
-
34
- it_behaves_like 'a failing predicate'
35
- end
36
- end
37
- end
@@ -1,37 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'dry/logic/predicates'
4
-
5
- RSpec.describe Dry::Logic::Predicates do
6
- describe '#type?' do
7
- let(:predicate_name) { :type? }
8
-
9
- context 'when value has a correct type' do
10
- let(:arguments_list) do
11
- [[TrueClass, true]]
12
- end
13
-
14
- it_behaves_like 'a passing predicate'
15
- end
16
-
17
- context 'with value is not true' do
18
- let(:arguments_list) do
19
- [
20
- [TrueClass, false],
21
- [TrueClass, ''],
22
- [TrueClass, []],
23
- [TrueClass, {}],
24
- [TrueClass, nil],
25
- [TrueClass, :symbol],
26
- [TrueClass, String],
27
- [TrueClass, 1],
28
- [TrueClass, 0],
29
- [TrueClass, 'true'],
30
- [TrueClass, 'false']
31
- ]
32
- end
33
-
34
- it_behaves_like 'a failing predicate'
35
- end
36
- end
37
- end
@@ -1,29 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'dry/logic/predicates'
4
-
5
- RSpec.describe Dry::Logic::Predicates do
6
- describe '#uuid_v4?' do
7
- let(:predicate_name) { :uuid_v4? }
8
-
9
- context 'when value is a valid V4 UUID' do
10
- let(:arguments_list) do
11
- [['f2d26c57-e07c-4416-a749-57e937930e04']]
12
- end
13
-
14
- it_behaves_like 'a passing predicate'
15
- end
16
-
17
- context 'with value is not a valid V4 UUID' do
18
- let(:arguments_list) do
19
- [
20
- ['f2d26c57-e07c-3416-a749-57e937930e04'], # wrong version number (3, not 4)
21
- ['20633928-6a07-11e9-a923-1681be663d3e'], # UUID V1
22
- ['not-a-uuid-at-all']
23
- ]
24
- end
25
-
26
- it_behaves_like 'a failing predicate'
27
- end
28
- end
29
- end
@@ -1,25 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'dry/logic/predicates'
4
-
5
- RSpec.describe Predicates do
6
- it 'can be included in another module' do
7
- mod = Module.new { include Predicates }
8
-
9
- expect(mod[:key?]).to be_a(Method)
10
- end
11
-
12
- describe '.predicate' do
13
- it 'defines a predicate method' do
14
- mod = Module.new {
15
- include Predicates
16
-
17
- predicate(:test?) do |foo|
18
- true
19
- end
20
- }
21
-
22
- expect(mod.test?('arg')).to be(true)
23
- end
24
- end
25
- end
@@ -1,55 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- RSpec.describe Rule::Predicate do
4
- subject(:rule) { Rule::Predicate.build(predicate) }
5
-
6
- let(:predicate) { str? }
7
-
8
- include_context 'predicates'
9
-
10
- it_behaves_like Rule
11
-
12
- describe '#name' do
13
- it 'returns predicate identifier' do
14
- expect(rule.name).to be(:str?)
15
- end
16
- end
17
-
18
- describe '#to_ast' do
19
- context 'without a result' do
20
- it 'returns rule ast' do
21
- expect(rule.to_ast).to eql([:predicate, [:str?, [[:input, Undefined]]]])
22
- end
23
-
24
- it 'returns :failure with an id' do
25
- email = rule.with(id: :email)
26
-
27
- expect(email.(11).to_ast).to eql([:failure, [:email, [:predicate, [:str?, [[:input, 11]]]]]])
28
- end
29
- end
30
-
31
- context 'with a result' do
32
- it 'returns success' do
33
- expect(rule.('foo')).to be_success
34
- end
35
-
36
- it 'returns failure ast' do
37
- expect(rule.(5).to_ast).to eql([:predicate, [:str?, [[:input, 5]]]])
38
- end
39
- end
40
-
41
- context 'with a zero-arity predicate' do
42
- let(:predicate) { Module.new { def self.test?; true; end }.method(:test?) }
43
-
44
- it 'returns ast' do
45
- expect(rule.to_ast).to eql([:predicate, [:test?, []]])
46
- end
47
- end
48
- end
49
-
50
- describe '#to_s' do
51
- it 'returns string representation' do
52
- expect(rule.curry('foo').to_s).to eql('str?("foo")')
53
- end
54
- end
55
- end
@@ -1,129 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'dry/logic/rule_compiler'
4
-
5
- RSpec.describe Dry::Logic::RuleCompiler, '#call' do
6
- subject(:compiler) { RuleCompiler.new(predicates) }
7
-
8
- let(:predicates) {
9
- { key?: predicate,
10
- attr?: predicate,
11
- filled?: predicate,
12
- gt?: predicate,
13
- one: predicate }
14
- }
15
-
16
- let(:predicate) { double(:predicate, name: :test?, arity: 2).as_null_object }
17
-
18
- let(:rule) { Rule::Predicate.build(predicate) }
19
- let(:key_op) { Operations::Key.new(rule, name: :email) }
20
- let(:attr_op) { Operations::Attr.new(rule, name: :email) }
21
- let(:check_op) { Operations::Check.new(rule, keys: [:email]) }
22
- let(:not_key_op) { Operations::Negation.new(key_op) }
23
- let(:and_op) { key_op.curry(:email) & rule }
24
- let(:or_op) { key_op.curry(:email) | rule }
25
- let(:xor_op) { key_op.curry(:email) ^ rule }
26
- let(:set_op) { Operations::Set.new(rule) }
27
- let(:each_op) { Operations::Each.new(rule) }
28
-
29
- it 'compiles key rules' do
30
- ast = [[:key, [:email, [:predicate, [:filled?, [[:input, Undefined]]]]]]]
31
-
32
- rules = compiler.(ast)
33
-
34
- expect(rules).to eql([key_op])
35
- end
36
-
37
- it 'compiles attr rules' do
38
- ast = [[:attr, [:email, [:predicate, [:filled?, [[:input, Undefined]]]]]]]
39
-
40
- rules = compiler.(ast)
41
-
42
- expect(rules).to eql([attr_op])
43
- end
44
-
45
- it 'compiles check rules' do
46
- ast = [[:check, [[:email], [:predicate, [:filled?, [[:input, Undefined]]]]]]]
47
-
48
- rules = compiler.(ast)
49
-
50
- expect(rules).to eql([check_op])
51
- end
52
-
53
- it 'compiles attr rules' do
54
- ast = [[:attr, [:email, [:predicate, [:filled?, [[:input, Undefined]]]]]]]
55
-
56
- rules = compiler.(ast)
57
-
58
- expect(rules).to eql([attr_op])
59
- end
60
-
61
- it 'compiles negated rules' do
62
- ast = [[:not, [:key, [:email, [:predicate, [:filled?, [[:input, Undefined]]]]]]]]
63
-
64
- rules = compiler.(ast)
65
-
66
- expect(rules).to eql([not_key_op])
67
- end
68
-
69
- it 'compiles and rules' do
70
- ast = [
71
- [
72
- :and, [
73
- [:key, [:email, [:predicate, [:key?, [[:name, :email], [:input, Undefined]]]]]],
74
- [:predicate, [:filled?, [[:input, Undefined]]]]
75
- ]
76
- ]
77
- ]
78
-
79
- rules = compiler.(ast)
80
-
81
- expect(rules).to eql([and_op])
82
- end
83
-
84
- it 'compiles or rules' do
85
- ast = [
86
- [
87
- :or, [
88
- [:key, [:email, [:predicate, [:key?, [[:name, :email], [:input, Undefined]]]]]],
89
- [:predicate, [:filled?, [[:input, Undefined]]]]
90
- ]
91
- ]
92
- ]
93
-
94
- rules = compiler.(ast)
95
-
96
- expect(rules).to eql([or_op])
97
- end
98
-
99
- it 'compiles exclusive or rules' do
100
- ast = [
101
- [
102
- :xor, [
103
- [:key, [:email, [:predicate, [:key?, [[:name, :email], [:input, Undefined]]]]]],
104
- [:predicate, [:filled?, [[:input, Undefined]]]]
105
- ]
106
- ]
107
- ]
108
-
109
- rules = compiler.(ast)
110
-
111
- expect(rules).to eql([xor_op])
112
- end
113
-
114
- it 'compiles set rules' do
115
- ast = [[:set, [[:predicate, [:filled?, [[:input, nil]]]]]]]
116
-
117
- rules = compiler.(ast)
118
-
119
- expect(rules).to eql([set_op])
120
- end
121
-
122
- it 'compiles each rules' do
123
- ast = [[:each, [:predicate, [:filled?, [[:input, nil]]]]]]
124
-
125
- rules = compiler.(ast)
126
-
127
- expect(rules).to eql([each_op])
128
- end
129
- end
@@ -1,213 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- RSpec.describe Dry::Logic::Rule do
4
- subject(:rule) { Rule.build(predicate, **options) }
5
-
6
- let(:predicate) { -> { true } }
7
- let(:options) { {} }
8
-
9
- let(:schema) do
10
- Class.new do
11
- define_method(:class, Kernel.instance_method(:class))
12
-
13
- def method_missing(m, *)
14
- if m.to_s.end_with?('?')
15
- self.class.new
16
- else
17
- super
18
- end
19
- end
20
-
21
- def to_proc
22
- -> value { value }
23
- end
24
-
25
- def arity
26
- 1
27
- end
28
-
29
- def parameters
30
- [[:req, :value]]
31
- end
32
- end.new
33
- end
34
-
35
- it_behaves_like Dry::Logic::Rule
36
-
37
- describe '.new' do
38
- it 'accepts an :id' do
39
- expect(Rule.build(predicate, id: :check_num).id).to be(:check_num)
40
- end
41
- end
42
-
43
- describe 'with a function returning truthy value' do
44
- it 'is successful for valid input' do
45
- expect(Rule.build(-> val { val }).('true')).to be_success
46
- end
47
-
48
- it 'is not successful for invalid input' do
49
- expect(Rule.build(-> val { val }).(nil)).to be_failure
50
- end
51
- end
52
-
53
- describe '#ast' do
54
- it 'returns predicate node with :id' do
55
- expect(Rule.build(-> value { true }).with(id: :email?).ast('oops')).to eql(
56
- [:predicate, [:email?, [[:value, 'oops']]]]
57
- )
58
- end
59
-
60
- it 'returns predicate node with undefined args' do
61
- expect(Rule.build(-> value { true }).with(id: :email?).ast).to eql(
62
- [:predicate, [:email?, [[:value, Undefined]]]]
63
- )
64
- end
65
- end
66
-
67
- describe '#type' do
68
- it 'returns rule type' do
69
- expect(rule.type).to be(:rule)
70
- end
71
- end
72
-
73
- describe '#bind' do
74
- let(:bound) { rule.with(id: :bound).bind(object) }
75
-
76
- context 'with an unbound method' do
77
- let(:predicate) { klass.instance_method(:test?) }
78
- let(:klass) { Class.new { def test?; true; end } }
79
- let(:object) { klass.new }
80
-
81
- it 'returns a new rule with its predicate bound to a specific object' do
82
- expect(bound.()).to be_success
83
- end
84
-
85
- it 'carries id' do
86
- expect(bound.id).to be(:bound)
87
- end
88
- end
89
-
90
- context 'with an arbitrary block' do
91
- let(:predicate) { -> value { value == expected } }
92
- let(:object) { Class.new { def expected; 'test'; end }.new }
93
-
94
- it 'returns a new with its predicate executed in the context of the provided object' do
95
- expect(bound.('test')).to be_success
96
- expect(bound.('oops')).to be_failure
97
- end
98
-
99
- it 'carries id' do
100
- expect(bound.id).to be(:bound)
101
- end
102
-
103
- it 'stores arity' do
104
- expect(bound.options[:arity]).to be(rule.arity)
105
- end
106
-
107
- it 'stores parameters' do
108
- expect(bound.options[:parameters]).to eql(rule.parameters)
109
- end
110
- end
111
-
112
- context 'with a schema instance' do
113
- let(:object) { schema }
114
- let(:predicate) { schema }
115
-
116
- it 'returns a new with its predicate executed in the context of the provided object' do
117
- expect(bound.(true)).to be_success
118
- expect(bound.(false)).to be_failure
119
- end
120
- end
121
- end
122
-
123
- describe '#eval_args' do
124
- context 'with an unbound method' do
125
- let(:options) { { args: [1, klass.instance_method(:num), :foo], arity: 3 } }
126
- let(:klass) { Class.new { def num; 7; end } }
127
- let(:object) { klass.new }
128
-
129
- it 'evaluates args in the context of the provided object' do
130
- expect(rule.eval_args(object).args).to eql([1, 7, :foo])
131
- end
132
- end
133
-
134
- context 'with a schema instance' do
135
- let(:options) { { args: [1, schema, :foo], arity: 3 } }
136
- let(:object) { Object.new }
137
-
138
- it 'returns a new with its predicate executed in the context of the provided object' do
139
- expect(rule.eval_args(object).args).to eql([1, schema, :foo])
140
- end
141
- end
142
- end
143
-
144
- describe 'arity specialization' do
145
- describe '0-arity rule' do
146
- let(:options) { { args: [1], arity: 1 } }
147
- let(:predicate) { :odd?.to_proc }
148
-
149
- it 'generates interface with the right arity' do
150
- expect(rule.method(:call).arity).to be_zero
151
- expect(rule.method(:[]).arity).to be_zero
152
- expect(rule[]).to be(true)
153
- expect(rule.()).to be_success
154
- end
155
- end
156
-
157
- describe '1-arity rule' do
158
- let(:options) { { args: [1], arity: 2 } }
159
- let(:predicate) { -> a, b { a + b } }
160
-
161
- it 'generates interface with the right arity' do
162
- expect(rule.method(:call).arity).to be(1)
163
- expect(rule.method(:[]).arity).to be(1)
164
- expect(rule[10]).to be(11)
165
- expect(rule.(1)).to be_success
166
- end
167
- end
168
-
169
- describe 'currying' do
170
- let(:options) { { args: [], arity: 2 } }
171
- let(:predicate) { -> a, b { a + b } }
172
- let(:rule) { super().curry(1) }
173
-
174
- it 'generates correct arity on currying' do
175
- expect(rule.method(:call).arity).to be(1)
176
- expect(rule.method(:[]).arity).to be(1)
177
- expect(rule[10]).to be(11)
178
- expect(rule.(1)).to be_success
179
- end
180
- end
181
-
182
- describe 'arbitrary arity' do
183
- let(:arity) { rand(1..20) }
184
- let(:curried) { rand(arity) }
185
-
186
- let(:options) { { args: [1] * curried, arity: arity } }
187
- let(:predicate) { double(:predicate) }
188
-
189
- it 'generates correct arity' do
190
- expect(rule.method(:call).arity).to be(arity - curried)
191
- expect(rule.method(:[]).arity).to be(arity - curried)
192
- end
193
- end
194
-
195
- describe '-1 arity' do
196
- let(:options) { { args: [], arity: -1 } }
197
-
198
- it 'accepts variable number of arguments' do
199
- expect(rule.method(:call).arity).to be(-1)
200
- expect(rule.method(:[]).arity).to be(-1)
201
- end
202
- end
203
-
204
- describe 'constants' do
205
- let(:options) { { args: [], arity: 0 } }
206
-
207
- it 'accepts variable number of arguments' do
208
- expect(rule.method(:call).arity).to be(-1)
209
- expect(rule.method(:[]).arity).to be(-1)
210
- end
211
- end
212
- end
213
- end