strong_json 1.0.1 → 1.1.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.
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