rschema 0.2.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (4) hide show
  1. checksums.yaml +4 -4
  2. data/lib/rschema.rb +35 -20
  3. data/lib/rschema/version.rb +1 -1
  4. metadata +17 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 795f0dd37dcc401fea7ff046c45d0ff3d80c033f
4
- data.tar.gz: 714901909ddda803bbe48b334985792e5e7e1498
3
+ metadata.gz: 9a5600f4f1f9cbe2d7743bd360a7005fa6b01da7
4
+ data.tar.gz: af415074e5917d934775f1d1c96b9afea39539f4
5
5
  SHA512:
6
- metadata.gz: c1c2cb7fd88e82014f772610481550d9bd97c9134edd3899d0798ec4d67bbcf5eaa9f474b4114d20a9ca22d620b1d7a69b3743e6e10a6310267134eb093b42d7
7
- data.tar.gz: 1c1987c9651e704228723d0c2765e9655589f94d180c64afc3cf4923383adf05be6c2e1beb246fab15dc650c544d75dc062e7e52c7308b7c44a978021c011983
6
+ metadata.gz: 6683829451d8153d46d7e66aac10939a27191ba47664103b8f33d35f937298755325d389857c1df065d0a0b3f7658825ef33a02d2a1d4da096d42f9df4ec62c6
7
+ data.tar.gz: 164aaf435884ae2fdbd6ffc84c779dbb922a328527b1e392316934bde24cfedfed272cf35d3505d2241bf3d4256da6261ae2444bc96d75dc00847b9b12715708
data/lib/rschema.rb CHANGED
@@ -4,16 +4,27 @@ module RSchema
4
4
  InvalidSchemaError = Class.new(StandardError)
5
5
  ValidationError = Class.new(StandardError)
6
6
  OptionalHashKey = Struct.new(:key)
7
- ErrorDetails = Struct.new(:details) do
8
- def to_s; inspect; end
9
- def inspect; details.inspect; end
7
+ ErrorDetails = Struct.new(:failing_value, :reason, :key_path) do
8
+ def initialize(failing_value, reason, key_path = [])
9
+ super(failing_value, reason, key_path)
10
+ end
11
+
12
+ def to_s
13
+ prefix = (key_path.empty? ? 'The root value' : "The value at #{key_path.inspect}")
14
+ "#{prefix} #{reason}: #{failing_value.inspect}"
15
+ end
16
+
17
+ def extend_key_path(key)
18
+ key_path.unshift(key)
19
+ self
20
+ end
10
21
  end
11
22
 
12
23
  def self.schema(&block)
13
24
  DSL.instance_exec(&block)
14
25
  end
15
26
 
16
- def self.validation_errors(schema, value)
27
+ def self.validation_error(schema, value)
17
28
  _, error = walk(schema, value)
18
29
  error
19
30
  end
@@ -27,6 +38,10 @@ module RSchema
27
38
  end
28
39
  end
29
40
 
41
+ def self.validate(schema, value)
42
+ validation_error(schema, value).nil?
43
+ end
44
+
30
45
  def self.coerce(schema, value)
31
46
  walk(schema, value, CoercionMapper)
32
47
  end
@@ -141,17 +156,17 @@ module RSchema
141
156
  GenericHashSchema = Struct.new(:key_subschema, :value_subschema) do
142
157
  def schema_walk(value, mapper)
143
158
  if not value.is_a?(Hash)
144
- return RSchema::ErrorDetails.new('is not a Hash')
159
+ return RSchema::ErrorDetails.new(value, 'is not a Hash')
145
160
  end
146
161
 
147
162
  value.reduce({}) do |accum, (k, v)|
148
163
  # walk key
149
164
  k_walked, error = RSchema.walk(key_subschema, k, mapper)
150
- break RSchema::ErrorDetails.new({'has invalid key, where' => error.details}) if error
165
+ break error.extend_key_path('.keys') if error
151
166
 
152
167
  # walk value
153
168
  v_walked, error = RSchema.walk(value_subschema, v, mapper)
154
- break RSchema::ErrorDetails.new({k => error.details}) if error
169
+ break error.extend_key_path(k) if error
155
170
 
156
171
  accum[k_walked] = v_walked
157
172
  accum
@@ -161,11 +176,11 @@ module RSchema
161
176
 
162
177
  GenericSetSchema = Struct.new(:subschema) do
163
178
  def schema_walk(value, mapper)
164
- return RSchema::ErrorDetails.new('is not a Set') if not value.is_a?(Set)
179
+ return RSchema::ErrorDetails.new(value, 'is not a Set') if not value.is_a?(Set)
165
180
 
166
181
  value.reduce(Set.new) do |accum, subvalue|
167
182
  subvalue_walked, error = RSchema.walk(subschema, subvalue, mapper)
168
- break RSchema::ErrorDetails.new(Set.new([error.details + ": " + subvalue.to_s])) if error
183
+ break error.extend_key_path('.values') if error
169
184
 
170
185
  accum << subvalue_walked
171
186
  accum
@@ -178,7 +193,7 @@ module RSchema
178
193
  if block.call(value)
179
194
  value
180
195
  else
181
- RSchema::ErrorDetails.new('fails predicate' + (name ? ": #{name}" : ''))
196
+ RSchema::ErrorDetails.new(value, 'fails predicate' + (name ? ": #{name}" : ''))
182
197
  end
183
198
  end
184
199
  end
@@ -207,7 +222,7 @@ module RSchema
207
222
  if value_set.include?(value_walked)
208
223
  value_walked
209
224
  else
210
- RSchema::ErrorDetails.new("#{value_walked} is not a valid enum member")
225
+ RSchema::ErrorDetails.new(value_walked, "#{value_walked} is not a valid enum member")
211
226
  end
212
227
  end
213
228
  end
@@ -217,7 +232,7 @@ module RSchema
217
232
  if value.is_a?(TrueClass) || value.is_a?(FalseClass)
218
233
  value
219
234
  else
220
- RSchema::ErrorDetails.new('is not a boolean')
235
+ RSchema::ErrorDetails.new(value, 'is not a boolean')
221
236
  end
222
237
  end
223
238
  end
@@ -228,7 +243,7 @@ class Class
228
243
  if value.is_a?(self)
229
244
  value
230
245
  else
231
- RSchema::ErrorDetails.new("is not a #{self.name}, is a #{value.class.name}")
246
+ RSchema::ErrorDetails.new(value, "is not a #{self.name}, is a #{value.class.name}")
232
247
  end
233
248
  end
234
249
  end
@@ -238,14 +253,14 @@ class Array
238
253
  fixed_size = (size != 1)
239
254
 
240
255
  if not value.is_a?(Array)
241
- RSchema::ErrorDetails.new("is not an Array")
256
+ RSchema::ErrorDetails.new(value, 'is not an Array')
242
257
  elsif fixed_size && value.size != size
243
- RSchema::ErrorDetails.new("does not have #{size} elements")
258
+ RSchema::ErrorDetails.new(value, "does not have #{size} elements")
244
259
  else
245
260
  value.each.with_index.map do |subvalue, idx|
246
261
  subschema = (fixed_size ? self[idx] : first)
247
262
  subvalue_walked, error = RSchema.walk(subschema, subvalue, mapper)
248
- break RSchema::ErrorDetails.new({ idx => error.details }) if error
263
+ break error.extend_key_path(idx) if error
249
264
  subvalue_walked
250
265
  end
251
266
  end
@@ -254,7 +269,7 @@ end
254
269
 
255
270
  class Hash
256
271
  def schema_walk(value, mapper)
257
- return RSchema::ErrorDetails.new('is not a Hash') if not value.is_a?(Hash)
272
+ return RSchema::ErrorDetails.new(value, 'is not a Hash') if not value.is_a?(Hash)
258
273
 
259
274
  # extract details from the schema
260
275
  required_keys = Set.new
@@ -271,19 +286,19 @@ class Hash
271
286
  # check for extra keys that shouldn't be there
272
287
  extraneous = value.keys.reject{ |k| all_subschemas.has_key?(k) }
273
288
  if extraneous.size > 0
274
- return RSchema::ErrorDetails.new({"has extraneous keys" => extraneous})
289
+ return RSchema::ErrorDetails.new(value, "has extraneous keys: #{extraneous.inspect}")
275
290
  end
276
291
 
277
292
  # check for required keys that are missing
278
293
  missing_requireds = required_keys.reject{ |k| value.has_key?(k) }
279
294
  if missing_requireds.size > 0
280
- return RSchema::ErrorDetails.new({"is missing required keys" => missing_requireds})
295
+ return RSchema::ErrorDetails.new(value, "is missing required keys: #{missing_requireds.inspect}")
281
296
  end
282
297
 
283
298
  # walk the subvalues
284
299
  value.reduce({}) do |accum, (k, subvalue)|
285
300
  subvalue_walked, error = RSchema.walk(all_subschemas[k], subvalue, mapper)
286
- break RSchema::ErrorDetails.new({ k => error.details }) if error
301
+ break error.extend_key_path(k) if error
287
302
  accum[k] = subvalue_walked
288
303
  accum
289
304
  end
@@ -1,3 +1,3 @@
1
1
  module RSchema
2
- VERSION = '0.2.0'
2
+ VERSION = '1.0.0'
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rschema
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tom Dalling
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-02-12 00:00:00.000000000 Z
11
+ date: 2015-02-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rspec
@@ -38,6 +38,20 @@ dependencies:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: gem-release
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '0.7'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '0.7'
41
55
  - !ruby/object:Gem::Dependency
42
56
  name: pry
43
57
  requirement: !ruby/object:Gem::Requirement
@@ -54,7 +68,7 @@ dependencies:
54
68
  version: '0'
55
69
  description: |2
56
70
  Schema-based validation and coercion for Ruby data structures. Heavily inspired
57
- by (read: stolen from) [Prismatic/schema][] for Clojure.
71
+ by (read: stolen from) Prismatic/schema for Clojure.
58
72
  email:
59
73
  - tom@tomdalling.com
60
74
  executables: []