val 0.0.4 → 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
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.