val 0.0.4 → 0.0.5

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 (3) hide show
  1. checksums.yaml +4 -4
  2. data/lib/val.rb +234 -59
  3. metadata +3 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 9247cdb7fe4d2b3a94295af7b84796bab9cd79b2
4
- data.tar.gz: eac3b09428e4dc6ba85899ff2654c22c12e5763f
3
+ metadata.gz: e559084125a92229a00c3246d741fa71bb48cf8b
4
+ data.tar.gz: 4f1c1546d4735de70bc66f83402f9f092a17ac4a
5
5
  SHA512:
6
- metadata.gz: 062e46a526133f70db1bffa87b4d0c765f61de4bc511738f4ba1b7753060bb626488e4b9aa8de340e05bf0333e412ecd453e839e3f2e1ae492923d6878f6a9f0
7
- data.tar.gz: 9489c6a848da693fc028ae4a4c5579c0a9c3b329f40e17df79d3c5af3811f5320e2c5aadc6cd8827b647dcc3abfb5ee300a405077ee34fbea1e2aef17a4698a5
6
+ metadata.gz: 1165ae24e8e37316a5e33006980eccc368a4d3e7bb860fb8596b65ae28b6685a904f19a3509fe7d0b466091bcc13d5839ebf44ed32bd3f6189b3133ab3a70f26
7
+ data.tar.gz: cd434a87fb8e363a16a1a1de9b567cc1aa5e9303eba6a6ead4bf354a2fed06690eb0ae85c71233fcdb07093de5c22969b483fd03699950b937b6e870edd843c5
data/lib/val.rb CHANGED
@@ -1,55 +1,39 @@
1
1
  class Val
2
2
  module DSL
3
- def OR *all
4
- Op::OR[*all]
5
- end
6
-
7
3
  def val &block
8
4
  self.class.new &block
9
5
  end
10
6
 
11
- def key name, *conditions
12
- first = conditions.first
13
-
14
- if [Module, Val, NilClass].any? &[first, :is_a?]
15
- type = first
16
- @conditions << Key.new(name, type)
17
- else
18
- @conditions.concat conditions.map { |array|
19
- ArrayCondition.new name, array
20
- }
21
- end
7
+
8
+ def is array
9
+ @claims << Claim.new(array)
22
10
  end
23
11
 
24
12
  def is_a type
25
- condition = -> value { value.is_a? type }
26
- @conditions << condition
13
+ is [:is_a?, type]
27
14
  end
28
15
 
29
- def is array
30
- condition = -> value {
31
- begin
32
- array.to_proc === value
33
- rescue TypeError, ArgumentError
34
- false
35
- end
36
- }
37
- @conditions << condition
16
+ def key name, *conditions
17
+ conditions = [NotNil] if conditions.empty?
18
+ @claims += conditions.map { |condition| Key.new name, condition }
38
19
  end
39
20
 
40
- def m name
41
- condition = -> value {
42
- value.respond_to? name
43
- }
44
- @conditions << condition
21
+
22
+ def OR *values
23
+ claim = -> it { values.any? &[:===, it] }
24
+ @claims << claim
45
25
  end
46
- end
47
-
48
- module Op
49
- OR = -> *values do
50
- -> value do
51
- values.any? &[:===, value]
52
- end
26
+
27
+ def NOT question
28
+ claim = -> it { not it.send question }
29
+ @claims << claim
30
+ end
31
+
32
+
33
+ def m name, &block
34
+ message = Message.new name
35
+ message.instance_exec &block if block_given?
36
+ @claims << message
53
37
  end
54
38
  end
55
39
 
@@ -58,46 +42,237 @@ class Val
58
42
  include DSL
59
43
 
60
44
  def initialize &block
61
- @conditions = []
62
- result = instance_exec &block
63
- if @conditions.empty?
64
- condition = result
65
- @conditions << condition
66
- end
45
+ @claims = []
46
+ instance_exec &block if block_given?
47
+ end
48
+
49
+ attr_reader :claims
50
+
51
+ def to_val
52
+ self
67
53
  end
68
54
 
69
55
  def === value
70
- @conditions.all? &[:===, value]
56
+ claims.all? &[:===, value]
57
+ end
58
+
59
+ def [] value
60
+ Instance.new self, value
71
61
  end
72
62
 
73
63
  Bool = new { OR(true, false) }
64
+ NotNil = new { NOT :nil? }
74
65
 
75
- class ArrayCondition
76
- def initialize name, array
77
- @name, @proc = name, array.to_proc
66
+ class Claim
67
+ def initialize array
68
+ @array = array
69
+ @proc = array.to_proc
70
+ end
71
+
72
+ def proc
73
+ @proc
74
+ end
75
+
76
+ def to_a
77
+ @array
78
78
  end
79
79
 
80
80
  def === value
81
- @proc === value[@name]
82
- rescue ArgumentError
83
- false
81
+ self[value].ok?
82
+ end
83
+
84
+ def [] value
85
+ Instance.new self, value
86
+ end
87
+
88
+ class Instance
89
+ attr_reader :type, :value, :error
90
+
91
+ def initialize type, value
92
+ @type, @value = type, value
93
+ @ok = type.proc === value
94
+ rescue
95
+ @error = $!
96
+ @ok = false
97
+ end
98
+
99
+ def ok?
100
+ @ok
101
+ end
102
+ end
103
+ end
104
+
105
+ module CoreExt
106
+ class ::Object
107
+ def to_val
108
+ type = Val.new
109
+ type.is [self, :===]
110
+ type
111
+ end
112
+ end
113
+
114
+ class ::Array
115
+ def to_val
116
+ type = Val.new
117
+ type.is self
118
+ type
119
+ end
120
+ end
121
+ end
122
+
123
+ class Instance
124
+ def initialize type, value
125
+ @claims = type.claims.map &[value]
126
+ @ok = @claims.all? &:ok?
127
+
128
+ set_all_instances_of_type Key::Instance
129
+ set_all_instances_of_type Message::Instance
130
+
131
+ @type, @value = type, value
132
+ end
133
+
134
+
135
+ attr_reader :claims, :type, :value
136
+ attr_reader :keys, :messages,
137
+ :present_keys, :missing_keys,
138
+ :present_messages, :missing_messages
139
+
140
+
141
+ def m name
142
+ messages[name]
143
+ end
144
+
145
+ def key key
146
+ keys[key]
84
147
  end
148
+
149
+
150
+ def ok?
151
+ @ok
152
+ end
153
+
154
+ private
155
+ def set_all_instances_of_type type
156
+ instances = @claims.grep type
157
+ plural_name = "#{type.name.split('::')[1].downcase}s"
158
+
159
+ unless instances.empty?
160
+ instance_variable_set :"@#{plural_name}",
161
+ instances.map { |instance| [instance.name, instance] }.to_h
162
+
163
+ present_instances, missing_instances = instances.partition &:ok?
164
+ instance_variable_set :"@present_#{plural_name}", present_instances.map(&:name)
165
+ instance_variable_set :"@missing_#{plural_name}", missing_instances.map(&:name)
166
+ end
167
+ end
85
168
  end
86
169
 
87
170
  class Key
88
- def initialize name, type
89
- @name, @type = name, type
171
+ attr_reader :name, :type
172
+
173
+ def initialize name, condition
174
+ @name, @type = name, condition.to_val
90
175
  end
91
176
 
92
177
  def === value
93
- value.respond_to?(:[]) && value[@name] && valid_type?(value[@name])
178
+ self[value].ok?
179
+ end
180
+
181
+ def [] it
182
+ Instance.new self, it
183
+ end
184
+
185
+ class Instance
186
+ attr_reader :type, :name, :value, :error
187
+
188
+ def initialize key, it
189
+ @name, @type = key.name, key.type
190
+ @value = it[@name]
191
+
192
+ @ok = @type === @value
193
+ rescue
194
+ @error = $!
195
+ @ok = false
196
+ end
197
+
198
+ def ok?
199
+ @ok
200
+ end
201
+ end
202
+ end
203
+
204
+ class Message
205
+ def initialize name
206
+ @name = name
207
+ @arrows = []
208
+ end
209
+
210
+ attr_reader :name, :arrows
211
+
212
+ def arrow &block
213
+ @arrows << Arrow.new(@name, &block)
94
214
  end
95
215
 
96
- def valid_type? name
97
- if @type
98
- @type === name
99
- else
100
- true
216
+ def === value
217
+ self[value].ok?
218
+ end
219
+
220
+ def [] value
221
+ Instance.new self, value
222
+ end
223
+
224
+ class Arrow
225
+ def initialize name, &block
226
+ @name = name
227
+ instance_exec &block if block_given?
228
+ end
229
+
230
+ attr_reader :name, :input, :expected_output
231
+
232
+ def from *all
233
+ @input = all
234
+ end
235
+
236
+ def to one
237
+ @expected_output = one
238
+ end
239
+
240
+ def [] value
241
+ Instance.new self, value
242
+ end
243
+
244
+ class Instance
245
+ def initialize type, value
246
+ @actual_output = value.send type.name, *type.input
247
+ @ok = @actual_output == type.expected_output
248
+ rescue
249
+ @error = $!
250
+ end
251
+
252
+ attr_reader :error
253
+
254
+ def ok?
255
+ @ok
256
+ end
257
+ end
258
+ end
259
+
260
+ class Instance
261
+ def initialize type, value
262
+ @name = type.name
263
+ @available = value.respond_to? @name
264
+ @arrows = type.arrows.map &[value]
265
+ @ok = @available && @arrows.all?(&:ok?)
266
+ end
267
+
268
+ attr_reader :name, :arrows
269
+
270
+ def available?
271
+ @available
272
+ end
273
+
274
+ def ok?
275
+ @ok
101
276
  end
102
277
  end
103
278
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: val
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4
4
+ version: 0.0.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Anatoly Chernow
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-08-08 00:00:00.000000000 Z
11
+ date: 2017-08-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: to_proc
@@ -50,7 +50,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
50
50
  version: '0'
51
51
  requirements: []
52
52
  rubyforge_project:
53
- rubygems_version: 2.6.11
53
+ rubygems_version: 2.6.13
54
54
  signing_key:
55
55
  specification_version: 4
56
56
  summary: Validate values of Ruby objects.