strong_json 1.0.1 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0035c9edc36454dc79ce83f91e948c91c7a10935cc4c7dc1ab3c50113c209100
4
- data.tar.gz: b77289a1d16f20e2f29875e5156917f984587ad70f6d9bddd4aa4d7a62f40cb9
3
+ metadata.gz: bd9a6dd9efbb0ccca7cd5dfc14a415b4f408138724e5c4a4fe58d7fcc8fccafe
4
+ data.tar.gz: 02a451a69abca02dfdb418b13302b3bb6545cf23b0ec302698b65d2127d6f6d4
5
5
  SHA512:
6
- metadata.gz: d230d14df235f9831ea73287abd9aa6018053ead823a7816bb73516adfc3599e29d727295055ab2439c6342592ebe1331e91a74df775adff8f550524b5be2d41
7
- data.tar.gz: ac439273a3b6ef148f2f135b3f3c9820caf25831f8bfaae554971830b1c009d42242a6a614b7786eb2669c551e356eb66823375f2bbecf9f2a372bb9b3154228
6
+ metadata.gz: 4026edd18f863953d03652c5ea691a5ad6a88ba1db2ca8f5181da60974ebd70d10cf6cb09bc0d836583e285a9279d70b1dda43178881a3da37093e40ffd793b3
7
+ data.tar.gz: e2ca4033fe34c2f9b433c6a92f8b44484b7f30dfb89ca10fb5b0bed8a21370eb463e8444f5d28c3575c133bb879868c762fba36620a78f27b0886df59f1f970a
data/CHANGELOG.md CHANGED
@@ -2,6 +2,10 @@
2
2
 
3
3
  ## master
4
4
 
5
+ ## 1.1.0 (2019-06-09)
6
+
7
+ * [#15](https://github.com/soutaro/strong_json/pull/15): Add `hash` type
8
+
5
9
  ## 1.0.1 (2019-05-29)
6
10
 
7
11
  * Improve enum error reporting
data/README.md CHANGED
@@ -86,6 +86,11 @@ object(attrs).prohibit!(Set.new([:created_at, :updated_at])) # Destructive vers
86
86
  * The value must be an array
87
87
  * All elements in the array must be value of given `type`
88
88
 
89
+ ### hash(type)
90
+
91
+ * The value must be an object
92
+ * All values in the object must be value of given `type`
93
+
89
94
  ### optional(type)
90
95
 
91
96
  * The value can be `nil` (or not contained in an object)
@@ -202,7 +202,7 @@ class StrongJSON
202
202
  end
203
203
 
204
204
  def coerce(object, path: ErrorPath.root(self))
205
- unless object.is_a?(Hash)
205
+ unless object.is_a?(::Hash)
206
206
  raise TypeError.new(path: path, value: object)
207
207
  end
208
208
 
@@ -336,6 +336,37 @@ class StrongJSON
336
336
  end
337
337
  end
338
338
 
339
+ class Hash
340
+ include Match
341
+ include WithAlias
342
+
343
+ # @dynamic type
344
+ attr_reader :type
345
+
346
+ def initialize(type)
347
+ @type = type
348
+ end
349
+
350
+ def coerce(value, path: ErrorPath.root(self))
351
+ if value.is_a?(::Hash)
352
+ (_ = {}).tap do |result|
353
+ value.each do |k, v|
354
+ result[k] = type.coerce(v, path: path.dig(key: k, type: type))
355
+ end
356
+ end
357
+ else
358
+ raise TypeError.new(path: path, value: value)
359
+ end
360
+ end
361
+
362
+ def ==(other)
363
+ if other.is_a?(Hash)
364
+ # @type var other: Hash<any>
365
+ other.type == type
366
+ end
367
+ end
368
+ end
369
+
339
370
  class UnexpectedAttributeError < StandardError
340
371
  # @dynamic path, attribute
341
372
  attr_reader :path, :attribute
@@ -91,5 +91,13 @@ class StrongJSON
91
91
  def enum?(*types, detector: nil)
92
92
  optional(enum(*types, detector: detector))
93
93
  end
94
+
95
+ def hash(type)
96
+ StrongJSON::Type::Hash.new(type)
97
+ end
98
+
99
+ def hash?(type)
100
+ optional(hash(type))
101
+ end
94
102
  end
95
103
  end
@@ -1,5 +1,5 @@
1
1
  class StrongJSON
2
2
  # @dynamic initialize, let
3
3
 
4
- VERSION = "1.0.1"
4
+ VERSION = "1.1.0"
5
5
  end
data/sig/strong_json.rbi CHANGED
@@ -49,6 +49,8 @@ module StrongJSON::Types
49
49
  def literal?: <'x> ('x) -> Type::Optional<'x>
50
50
  def enum: <'x> (*_Schema<any>, ?detector: Type::detector?) -> Type::Enum<'x>
51
51
  def enum?: <'x> (*_Schema<any>, ?detector: Type::detector?) -> Type::Optional<'x>
52
+ def (incompatible) hash: <'x> (_Schema<'x>) -> Type::Hash<'x>
53
+ def hash?: <'x> (_Schema<'x>) -> Type::Optional<Hash<Symbol, 'x>>
52
54
  end
53
55
 
54
56
  class StrongJSON::ErrorReporter
data/sig/type.rbi CHANGED
@@ -59,18 +59,18 @@ class StrongJSON::Type::Object<'t>
59
59
  include Match
60
60
  include WithAlias
61
61
 
62
- attr_reader fields: Hash<Symbol, _Schema<any>>
62
+ attr_reader fields: ::Hash<Symbol, _Schema<any>>
63
63
  attr_reader ignored_attributes: :any | Set<Symbol> | nil
64
64
  attr_reader prohibited_attributes: Set<Symbol>
65
65
 
66
- def initialize: (Hash<Symbol, _Schema<'t>>, ignored_attributes: :any | Set<Symbol> | nil, prohibited_attributes: Set<Symbol>) -> any
66
+ def initialize: (::Hash<Symbol, _Schema<'t>>, ignored_attributes: :any | Set<Symbol> | nil, prohibited_attributes: Set<Symbol>) -> any
67
67
  def coerce: (any, ?path: ErrorPath) -> 't
68
68
 
69
69
  def ignore: (:any | Set<Symbol> | nil) -> self
70
70
  def ignore!: (:any | Set<Symbol> | nil) -> self
71
71
  def prohibit: (Set<Symbol>) -> self
72
72
  def prohibit!: (Set<Symbol>) -> self
73
- def update_fields: <'x> { (Hash<Symbol, _Schema<any>>) -> void } -> Object<'x>
73
+ def update_fields: <'x> { (::Hash<Symbol, _Schema<any>>) -> void } -> Object<'x>
74
74
  end
75
75
 
76
76
  type StrongJSON::Type::detector = ^(any) -> _Schema<any>?
@@ -114,3 +114,12 @@ class StrongJSON::Type::UnexpectedAttributeError < StandardError
114
114
  def type: -> _Schema<any>
115
115
  end
116
116
 
117
+ class StrongJSON::Type::Hash<'t>
118
+ include Match
119
+ include WithAlias
120
+
121
+ attr_reader type: _Schema<'t>
122
+
123
+ def initialize: (_Schema<'t>) -> any
124
+ def coerce: (any, ?path: ErrorPath) -> ::Hash<Symbol, 't>
125
+ end
data/spec/hash_spec.rb ADDED
@@ -0,0 +1,32 @@
1
+ require "strong_json"
2
+
3
+ describe StrongJSON::Type::Hash do
4
+ let(:number) { StrongJSON::Type::Base.new(:number) }
5
+
6
+ describe "#coerce" do
7
+ it "returns a hash" do
8
+ type = StrongJSON::Type::Hash.new(number)
9
+ expect(type.coerce({ foo: 123, bar: 234 })).to eq({ foo: 123, bar: 234 })
10
+ end
11
+
12
+ it "raises an error if number is given" do
13
+ type = StrongJSON::Type::Hash.new(number)
14
+
15
+ expect {
16
+ type.coerce(1)
17
+ }.to raise_error(StrongJSON::Type::TypeError) {|error|
18
+ expect(error.path.to_s).to eq("$")
19
+ }
20
+ end
21
+
22
+ it "raises an error if hash value is unexpected" do
23
+ type = StrongJSON::Type::Hash.new(number)
24
+
25
+ expect {
26
+ type.coerce({ foo: "hello" })
27
+ }.to raise_error(StrongJSON::Type::TypeError) {|error|
28
+ expect(error.path.to_s).to eq("$.foo")
29
+ }
30
+ end
31
+ end
32
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: strong_json
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Soutaro Matsumoto
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-05-28 00:00:00.000000000 Z
11
+ date: 2019-06-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -95,6 +95,7 @@ files:
95
95
  - spec/case_subsumption_operator_spec.rb
96
96
  - spec/enum_spec.rb
97
97
  - spec/error_spec.rb
98
+ - spec/hash_spec.rb
98
99
  - spec/json_spec.rb
99
100
  - spec/literal_spec.rb
100
101
  - spec/object_spec.rb
@@ -131,6 +132,7 @@ test_files:
131
132
  - spec/case_subsumption_operator_spec.rb
132
133
  - spec/enum_spec.rb
133
134
  - spec/error_spec.rb
135
+ - spec/hash_spec.rb
134
136
  - spec/json_spec.rb
135
137
  - spec/literal_spec.rb
136
138
  - spec/object_spec.rb