jsi 0.0.4 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.simplecov +3 -1
- data/CHANGELOG.md +48 -0
- data/LICENSE.md +613 -0
- data/README.md +84 -45
- data/jsi.gemspec +11 -14
- data/lib/jsi.rb +31 -12
- data/lib/jsi/base.rb +310 -344
- data/lib/jsi/base/to_rb.rb +2 -0
- data/lib/jsi/jsi_coder.rb +91 -0
- data/lib/jsi/json-schema-fragments.rb +3 -135
- data/lib/jsi/json.rb +3 -0
- data/lib/jsi/json/node.rb +72 -197
- data/lib/jsi/json/pointer.rb +419 -0
- data/lib/jsi/metaschema.rb +7 -0
- data/lib/jsi/metaschema_node.rb +218 -0
- data/lib/jsi/pathed_node.rb +118 -0
- data/lib/jsi/schema.rb +168 -223
- data/lib/jsi/schema_classes.rb +158 -0
- data/lib/jsi/simple_wrap.rb +12 -0
- data/lib/jsi/typelike_modules.rb +71 -45
- data/lib/jsi/util.rb +47 -57
- data/lib/jsi/version.rb +1 -1
- data/lib/schemas/json-schema.org/draft-04/schema.rb +7 -0
- data/lib/schemas/json-schema.org/draft-06/schema.rb +7 -0
- data/resources/icons/AGPL-3.0.png +0 -0
- data/test/base_array_test.rb +210 -84
- data/test/base_hash_test.rb +201 -58
- data/test/base_test.rb +212 -121
- data/test/jsi_coder_test.rb +85 -0
- data/test/jsi_json_arraynode_test.rb +26 -25
- data/test/jsi_json_hashnode_test.rb +40 -39
- data/test/jsi_json_node_test.rb +95 -126
- data/test/jsi_json_pointer_test.rb +102 -0
- data/test/jsi_typelike_as_json_test.rb +53 -0
- data/test/metaschema_node_test.rb +19 -0
- data/test/schema_module_test.rb +21 -0
- data/test/schema_test.rb +109 -97
- data/test/spreedly_openapi_test.rb +8 -0
- data/test/test_helper.rb +42 -8
- data/test/util_test.rb +14 -14
- metadata +54 -25
- data/LICENSE.txt +0 -21
- data/lib/jsi/schema_instance_json_coder.rb +0 -83
- data/lib/jsi/struct_json_coder.rb +0 -30
- data/test/schema_instance_json_coder_test.rb +0 -121
- data/test/struct_json_coder_test.rb +0 -130
data/test/test_helper.rb
CHANGED
@@ -2,8 +2,12 @@ require 'coveralls'
|
|
2
2
|
if Coveralls.will_run?
|
3
3
|
Coveralls.wear!
|
4
4
|
end
|
5
|
-
|
6
5
|
require 'simplecov'
|
6
|
+
|
7
|
+
require 'bundler/setup'
|
8
|
+
|
9
|
+
require 'byebug'
|
10
|
+
|
7
11
|
$LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
|
8
12
|
require 'jsi'
|
9
13
|
|
@@ -16,8 +20,6 @@ require 'minitest/reporters'
|
|
16
20
|
|
17
21
|
Minitest::Reporters.use! Minitest::Reporters::SpecReporter.new
|
18
22
|
|
19
|
-
require 'byebug'
|
20
|
-
|
21
23
|
class JSISpec < Minitest::Spec
|
22
24
|
if ENV['JSI_TEST_ALPHA']
|
23
25
|
# :nocov:
|
@@ -26,9 +28,41 @@ class JSISpec < Minitest::Spec
|
|
26
28
|
end
|
27
29
|
|
28
30
|
def assert_equal exp, act, msg = nil
|
29
|
-
msg = message(msg, E)
|
31
|
+
msg = message(msg, E) do
|
32
|
+
[].tap do |ms|
|
33
|
+
ms << diff(exp, act)
|
34
|
+
ms << "#{ANSI.red { 'expected' }}: #{exp.inspect}"
|
35
|
+
ms << "#{ANSI.green { 'actual' }}: #{act.inspect}"
|
36
|
+
if exp.respond_to?(:to_str) && act.respond_to?(:to_str)
|
37
|
+
ms << "#{ANSI.red { 'expected (str)' }}:"
|
38
|
+
ms << exp
|
39
|
+
ms << "#{ANSI.green { 'actual (str)' }}:"
|
40
|
+
ms << act
|
41
|
+
end
|
42
|
+
end.join("\n")
|
43
|
+
end
|
30
44
|
assert exp == act, msg
|
31
45
|
end
|
46
|
+
|
47
|
+
def assert_match matcher, obj, msg = nil
|
48
|
+
msg = message(msg) do
|
49
|
+
[].tap do |ms|
|
50
|
+
ms << "Expected match."
|
51
|
+
ms << "#{ANSI.red { 'matcher' }}: #{mu_pp matcher}"
|
52
|
+
ms << "#{ANSI.green { 'object' }}: #{mu_pp obj}"
|
53
|
+
ms << "#{ANSI.yellow { 'escaped' }}: #{Regexp.new(Regexp.escape(obj)).inspect}" if obj.is_a?(String)
|
54
|
+
end.join("\n")
|
55
|
+
end
|
56
|
+
assert_respond_to matcher, :"=~"
|
57
|
+
matcher = Regexp.new Regexp.escape matcher if String === matcher
|
58
|
+
assert matcher =~ obj, msg
|
59
|
+
end
|
60
|
+
|
61
|
+
def assert_is_a mod, obj, msg = nil
|
62
|
+
msg = message(msg) { "Expected instance of #{mod}. received #{obj.class}: #{mu_pp(obj)}" }
|
63
|
+
|
64
|
+
assert obj.is_a?(mod), msg
|
65
|
+
end
|
32
66
|
end
|
33
67
|
|
34
68
|
# register this to be the base class for specs instead of Minitest::Spec
|
@@ -42,8 +76,8 @@ class SortOfHash
|
|
42
76
|
def to_hash
|
43
77
|
@hash
|
44
78
|
end
|
45
|
-
include JSI::FingerprintHash
|
46
|
-
def
|
79
|
+
include JSI::Util::FingerprintHash
|
80
|
+
def jsi_fingerprint
|
47
81
|
{class: self.class, hash: @hash}
|
48
82
|
end
|
49
83
|
end
|
@@ -56,8 +90,8 @@ class SortOfArray
|
|
56
90
|
def to_ary
|
57
91
|
@ary
|
58
92
|
end
|
59
|
-
include JSI::FingerprintHash
|
60
|
-
def
|
93
|
+
include JSI::Util::FingerprintHash
|
94
|
+
def jsi_fingerprint
|
61
95
|
{class: self.class, ary: @ary}
|
62
96
|
end
|
63
97
|
end
|
data/test/util_test.rb
CHANGED
@@ -6,24 +6,24 @@ describe JSI::Util do
|
|
6
6
|
assert_equal({'a' => 'b', 'c' => 'd', nil => 3}, JSI.stringify_symbol_keys({a: 'b', 'c' => 'd', nil => 3}))
|
7
7
|
end
|
8
8
|
it 'stringifies HashNode keys' do
|
9
|
-
actual = JSI.stringify_symbol_keys(JSI::JSON::
|
10
|
-
expected = JSI::JSON::
|
9
|
+
actual = JSI.stringify_symbol_keys(JSI::JSON::Node.new_doc({a: 'b', 'c' => 'd', nil => 3}))
|
10
|
+
expected = JSI::JSON::Node.new_doc({'a' => 'b', 'c' => 'd', nil => 3})
|
11
11
|
assert_equal(expected, actual)
|
12
12
|
end
|
13
13
|
it 'stringifies JSI hash keys' do
|
14
|
-
|
15
|
-
expected = JSI.stringify_symbol_keys(
|
16
|
-
actual =
|
14
|
+
schema = JSI::Schema.new({type: 'object'})
|
15
|
+
expected = JSI.stringify_symbol_keys(schema.new_jsi({a: 'b', 'c' => 'd', nil => 3}))
|
16
|
+
actual = schema.new_jsi({'a' => 'b', 'c' => 'd', nil => 3})
|
17
17
|
assert_equal(expected, actual)
|
18
18
|
end
|
19
19
|
describe 'non-hash-like argument' do
|
20
20
|
it 'errors' do
|
21
21
|
err = assert_raises(ArgumentError) { JSI.stringify_symbol_keys(nil) }
|
22
22
|
assert_equal("expected argument to be a hash; got NilClass: nil", err.message)
|
23
|
-
err = assert_raises(ArgumentError) { JSI.stringify_symbol_keys(JSI::JSON::Node.
|
24
|
-
assert_equal("expected argument to be a hash; got JSI::JSON::Node: #<JSI::JSON::Node
|
25
|
-
err = assert_raises(ArgumentError) { JSI.stringify_symbol_keys(JSI.
|
26
|
-
|
23
|
+
err = assert_raises(ArgumentError) { JSI.stringify_symbol_keys(JSI::JSON::Node.new_doc(3)) }
|
24
|
+
assert_equal("expected argument to be a hash; got JSI::JSON::Node: #<JSI::JSON::Node # 3>", err.message)
|
25
|
+
err = assert_raises(ArgumentError) { JSI.stringify_symbol_keys(JSI::Schema.new({}).new_jsi(3)) }
|
26
|
+
assert_equal("expected argument to be a hash; got (JSI Schema Class: #): #<JSI 3>", err.message)
|
27
27
|
end
|
28
28
|
end
|
29
29
|
end
|
@@ -48,14 +48,14 @@ describe JSI::Util do
|
|
48
48
|
assert_equal(expected, actual)
|
49
49
|
end
|
50
50
|
it 'deep stringifies HashNode keys' do
|
51
|
-
actual = JSI.deep_stringify_symbol_keys(JSI::JSON::
|
52
|
-
expected = JSI::JSON::
|
51
|
+
actual = JSI.deep_stringify_symbol_keys(JSI::JSON::Node.new_doc({a: 'b', 'c' => {d: 0}, nil => 3}))
|
52
|
+
expected = JSI::JSON::Node.new_doc({'a' => 'b', 'c' => {'d' => 0}, nil => 3})
|
53
53
|
assert_equal(expected, actual)
|
54
54
|
end
|
55
55
|
it 'deep stringifies JSI instance' do
|
56
|
-
|
57
|
-
actual = JSI.deep_stringify_symbol_keys(
|
58
|
-
expected =
|
56
|
+
schema = JSI::Schema.new(type: 'object')
|
57
|
+
actual = JSI.deep_stringify_symbol_keys(schema.new_jsi(JSI::JSON::Node.new_doc({a: 'b', 'c' => {d: 0}, nil => 3})))
|
58
|
+
expected = schema.new_jsi(JSI::JSON::Node.new_doc({'a' => 'b', 'c' => {'d' => 0}, nil => 3}))
|
59
59
|
assert_equal(expected, actual)
|
60
60
|
end
|
61
61
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: jsi
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ethan
|
8
8
|
autorequire:
|
9
|
-
bindir:
|
9
|
+
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2020-07-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: json-schema
|
@@ -28,30 +28,30 @@ dependencies:
|
|
28
28
|
name: rake
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- - "
|
31
|
+
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '
|
33
|
+
version: '0'
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- - "
|
38
|
+
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: '
|
40
|
+
version: '0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: minitest
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- - "
|
45
|
+
- - ">="
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: '
|
47
|
+
version: '0'
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
|
-
- - "
|
52
|
+
- - ">="
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: '
|
54
|
+
version: '0'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: minitest-around
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -80,10 +80,24 @@ dependencies:
|
|
80
80
|
- - ">="
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '0'
|
83
|
-
|
84
|
-
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: scorpio
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
description: JSI offers an Object-Oriented representation for JSON data using JSON
|
98
|
+
Schemas
|
85
99
|
email:
|
86
|
-
- ethan@unth
|
100
|
+
- ethan.jsi@unth.net
|
87
101
|
executables: []
|
88
102
|
extensions: []
|
89
103
|
extra_rdoc_files: []
|
@@ -91,37 +105,49 @@ files:
|
|
91
105
|
- ".simplecov"
|
92
106
|
- ".yardopts"
|
93
107
|
- CHANGELOG.md
|
94
|
-
- LICENSE.
|
108
|
+
- LICENSE.md
|
95
109
|
- README.md
|
96
110
|
- Rakefile.rb
|
97
111
|
- jsi.gemspec
|
98
112
|
- lib/jsi.rb
|
99
113
|
- lib/jsi/base.rb
|
100
114
|
- lib/jsi/base/to_rb.rb
|
115
|
+
- lib/jsi/jsi_coder.rb
|
101
116
|
- lib/jsi/json-schema-fragments.rb
|
102
117
|
- lib/jsi/json.rb
|
103
118
|
- lib/jsi/json/node.rb
|
119
|
+
- lib/jsi/json/pointer.rb
|
120
|
+
- lib/jsi/metaschema.rb
|
121
|
+
- lib/jsi/metaschema_node.rb
|
122
|
+
- lib/jsi/pathed_node.rb
|
104
123
|
- lib/jsi/schema.rb
|
105
|
-
- lib/jsi/
|
106
|
-
- lib/jsi/
|
124
|
+
- lib/jsi/schema_classes.rb
|
125
|
+
- lib/jsi/simple_wrap.rb
|
107
126
|
- lib/jsi/typelike_modules.rb
|
108
127
|
- lib/jsi/util.rb
|
109
128
|
- lib/jsi/version.rb
|
129
|
+
- lib/schemas/json-schema.org/draft-04/schema.rb
|
130
|
+
- lib/schemas/json-schema.org/draft-06/schema.rb
|
131
|
+
- resources/icons/AGPL-3.0.png
|
110
132
|
- test/base_array_test.rb
|
111
133
|
- test/base_hash_test.rb
|
112
134
|
- test/base_test.rb
|
135
|
+
- test/jsi_coder_test.rb
|
113
136
|
- test/jsi_json_arraynode_test.rb
|
114
137
|
- test/jsi_json_hashnode_test.rb
|
115
138
|
- test/jsi_json_node_test.rb
|
139
|
+
- test/jsi_json_pointer_test.rb
|
116
140
|
- test/jsi_test.rb
|
117
|
-
- test/
|
141
|
+
- test/jsi_typelike_as_json_test.rb
|
142
|
+
- test/metaschema_node_test.rb
|
143
|
+
- test/schema_module_test.rb
|
118
144
|
- test/schema_test.rb
|
119
|
-
- test/
|
145
|
+
- test/spreedly_openapi_test.rb
|
120
146
|
- test/test_helper.rb
|
121
147
|
- test/util_test.rb
|
122
148
|
homepage: https://github.com/notEthan/jsi
|
123
149
|
licenses:
|
124
|
-
-
|
150
|
+
- AGPL-3.0
|
125
151
|
metadata: {}
|
126
152
|
post_install_message:
|
127
153
|
rdoc_options: []
|
@@ -138,21 +164,24 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
138
164
|
- !ruby/object:Gem::Version
|
139
165
|
version: '0'
|
140
166
|
requirements: []
|
141
|
-
|
142
|
-
rubygems_version: 2.7.8
|
167
|
+
rubygems_version: 3.0.6
|
143
168
|
signing_key:
|
144
169
|
specification_version: 4
|
145
|
-
summary: 'JSI: JSON
|
170
|
+
summary: 'JSI: JSON Schema Instantiation'
|
146
171
|
test_files:
|
147
172
|
- test/base_array_test.rb
|
148
173
|
- test/base_hash_test.rb
|
149
174
|
- test/base_test.rb
|
175
|
+
- test/jsi_coder_test.rb
|
150
176
|
- test/jsi_json_arraynode_test.rb
|
151
177
|
- test/jsi_json_hashnode_test.rb
|
152
178
|
- test/jsi_json_node_test.rb
|
179
|
+
- test/jsi_json_pointer_test.rb
|
153
180
|
- test/jsi_test.rb
|
154
|
-
- test/
|
181
|
+
- test/jsi_typelike_as_json_test.rb
|
182
|
+
- test/metaschema_node_test.rb
|
183
|
+
- test/schema_module_test.rb
|
155
184
|
- test/schema_test.rb
|
156
|
-
- test/
|
185
|
+
- test/spreedly_openapi_test.rb
|
157
186
|
- test/test_helper.rb
|
158
187
|
- test/util_test.rb
|
data/LICENSE.txt
DELETED
@@ -1,21 +0,0 @@
|
|
1
|
-
The MIT License (MIT)
|
2
|
-
|
3
|
-
Copyright (c) 2016 Ethan
|
4
|
-
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
7
|
-
in the Software without restriction, including without limitation the rights
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
10
|
-
furnished to do so, subject to the following conditions:
|
11
|
-
|
12
|
-
The above copyright notice and this permission notice shall be included in
|
13
|
-
all copies or substantial portions of the Software.
|
14
|
-
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
-
THE SOFTWARE.
|
@@ -1,83 +0,0 @@
|
|
1
|
-
module JSI
|
2
|
-
# this is a ActiveRecord serialization class intended to store JSON in the
|
3
|
-
# database column and expose a ruby class once loaded on a model instance.
|
4
|
-
# this allows for better ruby idioms to access to properties, and definition
|
5
|
-
# of related methods on the loaded class.
|
6
|
-
#
|
7
|
-
# the first argument, `loaded_class`, is the class which will be used to
|
8
|
-
# instantiate the column data. properties of the loaded class will correspond
|
9
|
-
# to keys of the json object in the database.
|
10
|
-
#
|
11
|
-
# the column data may be either a single instance of the loaded class
|
12
|
-
# (represented as one json object) or an array of them (represented as a json
|
13
|
-
# array of json objects), indicated by the keyword argument `array`.
|
14
|
-
#
|
15
|
-
# the column behind the attribute may be an actual JSON column (postgres json
|
16
|
-
# or jsonb - hstore should work too if you only have string attributes) or a
|
17
|
-
# serialized string, indicated by the keyword argument `string`.
|
18
|
-
class ObjectJSONCoder
|
19
|
-
class Error < StandardError
|
20
|
-
end
|
21
|
-
class LoadError < Error
|
22
|
-
end
|
23
|
-
class DumpError < Error
|
24
|
-
end
|
25
|
-
|
26
|
-
def initialize(loaded_class, string: false, array: false, next_coder: nil)
|
27
|
-
@loaded_class = loaded_class
|
28
|
-
# this notes the order of the keys as they were in the json, used by dump_object to generate
|
29
|
-
# json that is equivalent to the json/jsonifiable that came in, so that AR's #changed_attributes
|
30
|
-
# can tell whether the attribute has been changed.
|
31
|
-
@loaded_class.send(:attr_accessor, :object_json_coder_keys_order)
|
32
|
-
@string = string
|
33
|
-
@array = array
|
34
|
-
@next_coder = next_coder
|
35
|
-
end
|
36
|
-
|
37
|
-
def load(column_data)
|
38
|
-
return nil if column_data.nil?
|
39
|
-
data = @string ? ::JSON.parse(column_data) : column_data
|
40
|
-
object = if @array
|
41
|
-
unless data.respond_to?(:to_ary)
|
42
|
-
raise TypeError, "expected array-like column data; got: #{data.class}: #{data.inspect}"
|
43
|
-
end
|
44
|
-
data.map { |el| load_object(el) }
|
45
|
-
else
|
46
|
-
load_object(data)
|
47
|
-
end
|
48
|
-
object = @next_coder.load(object) if @next_coder
|
49
|
-
object
|
50
|
-
end
|
51
|
-
|
52
|
-
def dump(object)
|
53
|
-
object = @next_coder.dump(object) if @next_coder
|
54
|
-
return nil if object.nil?
|
55
|
-
jsonifiable = begin
|
56
|
-
if @array
|
57
|
-
unless object.respond_to?(:to_ary)
|
58
|
-
raise DumpError, "expected array-like attribute; got: #{object.class}: #{object.inspect}"
|
59
|
-
end
|
60
|
-
object.map do |el|
|
61
|
-
dump_object(el)
|
62
|
-
end
|
63
|
-
else
|
64
|
-
dump_object(object)
|
65
|
-
end
|
66
|
-
end
|
67
|
-
@string ? ::JSON.generate(jsonifiable) : jsonifiable
|
68
|
-
end
|
69
|
-
end
|
70
|
-
# this is a ActiveRecord serialization class intended to store JSON in the
|
71
|
-
# database column and expose a given JSI::Base subclass once loaded
|
72
|
-
# on a model instance.
|
73
|
-
class SchemaInstanceJSONCoder < ObjectJSONCoder
|
74
|
-
private
|
75
|
-
def load_object(data)
|
76
|
-
@loaded_class.new(data)
|
77
|
-
end
|
78
|
-
|
79
|
-
def dump_object(object)
|
80
|
-
JSI::Typelike.as_json(object)
|
81
|
-
end
|
82
|
-
end
|
83
|
-
end
|
@@ -1,30 +0,0 @@
|
|
1
|
-
module JSI
|
2
|
-
# this is a ActiveRecord serialization class intended to store JSON in the
|
3
|
-
# database column and expose a Struct subclass once loaded on a model instance.
|
4
|
-
class StructJSONCoder < ObjectJSONCoder
|
5
|
-
private
|
6
|
-
def load_object(data)
|
7
|
-
if data.is_a?(Hash)
|
8
|
-
good_keys = @loaded_class.members.map(&:to_s)
|
9
|
-
bad_keys = data.keys - good_keys
|
10
|
-
unless bad_keys.empty?
|
11
|
-
raise LoadError, "expected keys #{good_keys}; got unrecognized keys: #{bad_keys}"
|
12
|
-
end
|
13
|
-
instance = @loaded_class.new(*@loaded_class.members.map { |m| data[m.to_s] })
|
14
|
-
instance.object_json_coder_keys_order = data.keys
|
15
|
-
instance
|
16
|
-
else
|
17
|
-
raise LoadError, "expected instance(s) of #{Hash}; got: #{data.class}: #{data.inspect}"
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
def dump_object(object)
|
22
|
-
if object.is_a?(@loaded_class)
|
23
|
-
keys = (object.object_json_coder_keys_order || []) | @loaded_class.members.map(&:to_s)
|
24
|
-
keys.map { |member| {member => object[member]} }.inject({}, &:update)
|
25
|
-
else
|
26
|
-
raise TypeError, "expected instance(s) of #{@loaded_class}; got: #{object.class}: #{object.inspect}"
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|