rschema 0.2.0 → 1.0.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.
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: []