jsi 0.4.0 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.yardopts +1 -1
- data/CHANGELOG.md +15 -0
- data/README.md +105 -38
- data/lib/jsi/base.rb +349 -155
- data/lib/jsi/jsi_coder.rb +5 -4
- data/lib/jsi/metaschema_node/bootstrap_schema.rb +100 -0
- data/lib/jsi/metaschema_node.rb +156 -129
- data/lib/jsi/pathed_node.rb +47 -49
- data/lib/jsi/ptr.rb +292 -0
- data/lib/jsi/schema/application/child_application/contains.rb +16 -0
- data/lib/jsi/schema/application/child_application/draft04.rb +22 -0
- data/lib/jsi/schema/application/child_application/draft06.rb +29 -0
- data/lib/jsi/schema/application/child_application/draft07.rb +29 -0
- data/lib/jsi/schema/application/child_application/items.rb +18 -0
- data/lib/jsi/schema/application/child_application/properties.rb +25 -0
- data/lib/jsi/schema/application/child_application.rb +40 -0
- data/lib/jsi/schema/application/draft04.rb +8 -0
- data/lib/jsi/schema/application/draft06.rb +8 -0
- data/lib/jsi/schema/application/draft07.rb +8 -0
- data/lib/jsi/schema/application/inplace_application/dependencies.rb +28 -0
- data/lib/jsi/schema/application/inplace_application/draft04.rb +26 -0
- data/lib/jsi/schema/application/inplace_application/draft06.rb +27 -0
- data/lib/jsi/schema/application/inplace_application/draft07.rb +33 -0
- data/lib/jsi/schema/application/inplace_application/ifthenelse.rb +20 -0
- data/lib/jsi/schema/application/inplace_application/ref.rb +18 -0
- data/lib/jsi/schema/application/inplace_application/someof.rb +29 -0
- data/lib/jsi/schema/application/inplace_application.rb +46 -0
- data/lib/jsi/schema/application.rb +12 -0
- data/lib/jsi/schema/draft04.rb +14 -0
- data/lib/jsi/schema/draft06.rb +14 -0
- data/lib/jsi/schema/draft07.rb +14 -0
- data/lib/jsi/schema/issue.rb +36 -0
- data/lib/jsi/schema/ref.rb +159 -0
- data/lib/jsi/schema/schema_ancestor_node.rb +119 -0
- data/lib/jsi/schema/validation/array.rb +69 -0
- data/lib/jsi/schema/validation/const.rb +20 -0
- data/lib/jsi/schema/validation/contains.rb +25 -0
- data/lib/jsi/schema/validation/core.rb +39 -0
- data/lib/jsi/schema/validation/dependencies.rb +49 -0
- data/lib/jsi/schema/validation/draft04/minmax.rb +91 -0
- data/lib/jsi/schema/validation/draft04.rb +112 -0
- data/lib/jsi/schema/validation/draft06.rb +122 -0
- data/lib/jsi/schema/validation/draft07.rb +159 -0
- data/lib/jsi/schema/validation/enum.rb +25 -0
- data/lib/jsi/schema/validation/ifthenelse.rb +46 -0
- data/lib/jsi/schema/validation/items.rb +54 -0
- data/lib/jsi/schema/validation/not.rb +20 -0
- data/lib/jsi/schema/validation/numeric.rb +121 -0
- data/lib/jsi/schema/validation/object.rb +45 -0
- data/lib/jsi/schema/validation/pattern.rb +34 -0
- data/lib/jsi/schema/validation/properties.rb +101 -0
- data/lib/jsi/schema/validation/property_names.rb +32 -0
- data/lib/jsi/schema/validation/ref.rb +40 -0
- data/lib/jsi/schema/validation/required.rb +27 -0
- data/lib/jsi/schema/validation/someof.rb +90 -0
- data/lib/jsi/schema/validation/string.rb +47 -0
- data/lib/jsi/schema/validation/type.rb +49 -0
- data/lib/jsi/schema/validation.rb +51 -0
- data/lib/jsi/schema.rb +486 -133
- data/lib/jsi/schema_classes.rb +157 -42
- data/lib/jsi/schema_registry.rb +141 -0
- data/lib/jsi/schema_set.rb +141 -0
- data/lib/jsi/simple_wrap.rb +2 -2
- data/lib/jsi/typelike_modules.rb +52 -37
- data/lib/jsi/util/attr_struct.rb +106 -0
- data/lib/jsi/util.rb +141 -25
- data/lib/jsi/validation/error.rb +34 -0
- data/lib/jsi/validation/result.rb +210 -0
- data/lib/jsi/validation.rb +15 -0
- data/lib/jsi/version.rb +3 -1
- data/lib/jsi.rb +55 -9
- data/lib/schemas/json-schema.org/draft-04/schema.rb +8 -3
- data/lib/schemas/json-schema.org/draft-06/schema.rb +8 -3
- data/lib/schemas/json-schema.org/draft-07/schema.rb +12 -0
- data/readme.rb +138 -0
- data/{resources}/schemas/json-schema.org/draft-04/schema.json +149 -0
- data/{resources}/schemas/json-schema.org/draft-06/schema.json +154 -0
- data/{resources}/schemas/json-schema.org/draft-07/schema.json +168 -0
- metadata +69 -118
- data/.simplecov +0 -3
- data/Rakefile.rb +0 -9
- data/jsi.gemspec +0 -28
- data/lib/jsi/base/to_rb.rb +0 -128
- data/lib/jsi/json/node.rb +0 -203
- data/lib/jsi/json/pointer.rb +0 -419
- data/lib/jsi/json-schema-fragments.rb +0 -61
- data/lib/jsi/json.rb +0 -10
- data/resources/icons/AGPL-3.0.png +0 -0
- data/test/base_array_test.rb +0 -323
- data/test/base_hash_test.rb +0 -337
- data/test/base_test.rb +0 -486
- data/test/jsi_coder_test.rb +0 -85
- data/test/jsi_json_arraynode_test.rb +0 -150
- data/test/jsi_json_hashnode_test.rb +0 -132
- data/test/jsi_json_node_test.rb +0 -257
- data/test/jsi_json_pointer_test.rb +0 -102
- data/test/jsi_test.rb +0 -11
- data/test/jsi_typelike_as_json_test.rb +0 -53
- data/test/metaschema_node_test.rb +0 -19
- data/test/schema_module_test.rb +0 -21
- data/test/schema_test.rb +0 -208
- data/test/spreedly_openapi_test.rb +0 -8
- data/test/test_helper.rb +0 -97
- data/test/util_test.rb +0 -62
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0e03bfff724257e11f9001d2845666d25f317b3761d5b62dc39816ad3fa3c28e
|
4
|
+
data.tar.gz: d315e1424f2bd8eef67a2ad562c7668b6b8582b9bda25c8ba74cc892b1a9b1e4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e62b9bf206486a77a3d1202388ddcd0fb29d326abf5a0b19fd6e74454ae05a494e4f88dcddaa42c7fc0b8b071877a406f213cde4589b21383778d9c713aa91b7
|
7
|
+
data.tar.gz: a07b6d591b0cd8bfe28d5923018931f4ee8fc3dba393b240dbefd74a26e813e0a759ecab482be4da7a7e2fa3d4c74a0542c98fcef35364a1a07684e0dc24d2f0
|
data/.yardopts
CHANGED
@@ -1 +1 @@
|
|
1
|
-
--main README.md --markup=markdown {lib}/**/*.rb
|
1
|
+
--main README.md --markup=markdown --no-private {lib}/**/*.rb
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,18 @@
|
|
1
|
+
# v0.6.0
|
2
|
+
|
3
|
+
- initial validation; remove gem `json-schema` dependency
|
4
|
+
- initial schema issue collection
|
5
|
+
- JSI.new_schema / new_schema_module
|
6
|
+
- JSI::SchemaSet
|
7
|
+
- JSI::SchemaRegistry
|
8
|
+
- JSI::Schema::Ref
|
9
|
+
- Base#jsi_each_child_node, jsi_select_children_node_first, jsi_select_children_leaf_first
|
10
|
+
- JSI::JSON::Pointer → JSI::Ptr
|
11
|
+
- deprecate JSI.class_for_schemas
|
12
|
+
- remove test/development files from gem
|
13
|
+
- remove JSI::JSON::Node
|
14
|
+
- as always too much more to list
|
15
|
+
|
1
16
|
# v0.4.0
|
2
17
|
|
3
18
|
- a JSI::Base has multiple jsi_schemas https://github.com/notEthan/jsi/pull/88
|
data/README.md
CHANGED
@@ -5,15 +5,20 @@
|
|
5
5
|
|
6
6
|
JSI offers an Object-Oriented representation for JSON data using JSON Schemas. Given your JSON Schemas, JSI constructs Ruby modules and classes which are used to instantiate your JSON data. These modules let you use JSON with all the niceties of OOP such as property accessors and application-defined instance methods.
|
7
7
|
|
8
|
-
To learn more about JSON Schema see [https://json-schema.org/]().
|
8
|
+
To learn more about JSON Schema see [https://json-schema.org/](https://json-schema.org/).
|
9
9
|
|
10
|
-
|
10
|
+
JSI marries object-oriented programming with JSON Schemas by associating a module with each schema, and extending every instance described by a schema with that module. When an application adds methods to a schema module, those methods can be used on its instances.
|
11
|
+
|
12
|
+
A JSI instance aims to offer a fairly unobtrusive wrapper around its JSON data, which is usually a Hash (JSON Object) or Array described by one or more JSON Schemas. JSI instances have accessors for property names described by schemas, schema validation, and other nice things. Mostly though, you use a JSI as you would use its underlying data, calling the same methods (e.g. `#[]`, `#map`, `#repeated_permutation`) and passing it to anything that duck-types expecting `#to_ary` or `#to_hash`.
|
13
|
+
|
14
|
+
Note: The canonical location of this README is on [RubyDoc](http://rubydoc.info/gems/jsi/). When viewed on [Github](https://github.com/notEthan/jsi/), it may be inconsistent with the latest released gem, and Yardoc links will not work.
|
11
15
|
|
12
16
|
## Example
|
13
17
|
|
14
18
|
Words are boring, let's code. Here's a schema in yaml:
|
15
19
|
|
16
20
|
```yaml
|
21
|
+
$schema: "http://json-schema.org/draft-07/schema"
|
17
22
|
description: "A Contact"
|
18
23
|
type: "object"
|
19
24
|
properties:
|
@@ -28,11 +33,11 @@ properties:
|
|
28
33
|
number: {type: "string"}
|
29
34
|
```
|
30
35
|
|
31
|
-
|
36
|
+
We pass that to {JSI.new_schema} which will instantiate a JSI Schema which represents it:
|
32
37
|
|
33
38
|
```ruby
|
34
|
-
# this would usually
|
35
|
-
contact_schema = JSI
|
39
|
+
# this would usually load YAML or JSON; the schema object is inlined for copypastability.
|
40
|
+
contact_schema = JSI.new_schema({"$schema" => "http://json-schema.org/draft-07/schema", "description" => "A Contact", "type" => "object", "properties" => {"name" => {"type" => "string"}, "phone" => {"type" => "array", "items" => {"type" => "object", "properties" => {"location" => {"type" => "string"}, "number" => {"type" => "string"}}}}}})
|
36
41
|
```
|
37
42
|
|
38
43
|
We name the module that JSI will use when instantiating a contact. Named modules are better to work with, and JSI will indicate the names of schema modules in its `#inspect` output.
|
@@ -54,12 +59,12 @@ nickname: big b
|
|
54
59
|
So, if we construct an instance like:
|
55
60
|
|
56
61
|
```ruby
|
57
|
-
# this would usually
|
62
|
+
# this would usually load YAML or JSON; the schema instance is inlined for copypastability.
|
58
63
|
bill = Contact.new_jsi({"name" => "bill", "phone" => [{"location" => "home", "number" => "555"}], "nickname" => "big b"})
|
59
64
|
# => #{<JSI (Contact)>
|
60
65
|
# "name" => "bill",
|
61
|
-
# "phone" => #[<JSI>
|
62
|
-
# #{<JSI>
|
66
|
+
# "phone" => #[<JSI (Contact.properties["phone"])>
|
67
|
+
# #{<JSI (Contact.properties["phone"].items)>
|
63
68
|
# "location" => "home",
|
64
69
|
# "number" => "555"
|
65
70
|
# }
|
@@ -68,7 +73,7 @@ bill = Contact.new_jsi({"name" => "bill", "phone" => [{"location" => "home", "nu
|
|
68
73
|
# }
|
69
74
|
```
|
70
75
|
|
71
|
-
Note that the keys are strings. JSI, being designed with JSON in mind, is geared toward string keys.
|
76
|
+
Note that the hash keys are strings. JSI, being designed with JSON in mind, is geared toward string keys.
|
72
77
|
|
73
78
|
We get accessors for the Contact:
|
74
79
|
|
@@ -77,7 +82,7 @@ bill.name
|
|
77
82
|
# => "bill"
|
78
83
|
```
|
79
84
|
|
80
|
-
but also nested accessors -
|
85
|
+
but also nested accessors - `#phone` is an instance of its array-type schema, and each phone item is an instance of another object-type schema with `#location` and `#number` accessors:
|
81
86
|
|
82
87
|
```ruby
|
83
88
|
bill.phone.map(&:location)
|
@@ -87,34 +92,43 @@ bill.phone.map(&:location)
|
|
87
92
|
We also get validations, as you'd expect given that's largely what json-schema exists to do:
|
88
93
|
|
89
94
|
```ruby
|
90
|
-
bill.
|
95
|
+
bill.jsi_valid?
|
91
96
|
# => true
|
92
97
|
```
|
93
98
|
|
94
|
-
... and validations on the nested schema instances (
|
99
|
+
... and validations on the nested schema instances (`#phone` here), showing in this example validation failure on /phone/0/number:
|
95
100
|
|
96
101
|
```ruby
|
97
102
|
bad = Contact.new_jsi({'phone' => [{'number' => [5, 5, 5]}]})
|
98
103
|
# => #{<JSI (Contact)>
|
99
|
-
# "phone" => #[<JSI>
|
100
|
-
# #{<JSI>
|
101
|
-
# "number" => #[<JSI> 5, 5, 5]
|
104
|
+
# "phone" => #[<JSI (Contact.properties["phone"])>
|
105
|
+
# #{<JSI (Contact.properties["phone"].items)>
|
106
|
+
# "number" => #[<JSI (Contact.properties["phone"].items.properties["number"])> 5, 5, 5]
|
102
107
|
# }
|
103
108
|
# ]
|
104
109
|
# }
|
105
|
-
bad.phone.
|
106
|
-
# =>
|
110
|
+
bad.phone.jsi_validate
|
111
|
+
# => #<JSI::Validation::FullResult
|
112
|
+
# @validation_errors=
|
113
|
+
# #<Set: {#<JSI::Validation::Error
|
114
|
+
# message: "instance type does not match `type` value",
|
115
|
+
# keyword: "type",
|
116
|
+
# schema: #{<JSI (JSI::JSONSchemaOrgDraft07) Schema> "type" => "string"},
|
117
|
+
# instance_ptr: JSI::Ptr["phone", 0, "number"],
|
118
|
+
# instance_document: {"phone"=>[{"number"=>[5, 5, 5]}]}
|
119
|
+
# >,
|
120
|
+
# ...
|
121
|
+
# >
|
107
122
|
```
|
108
123
|
|
109
|
-
These validations are done by the [`json-schema` gem](https://github.com/ruby-json-schema/json-schema) - JSI does not do validations on its own.
|
110
|
-
|
111
124
|
Since the underlying instance is a ruby hash (json object), we can use it like a hash with `#[]` or, say, `#transform_values`:
|
112
125
|
|
113
126
|
```ruby
|
114
|
-
# note that #size here is actually referring to multiple different methods;
|
115
|
-
# it is String#size but for phone it is Array#size.
|
127
|
+
# note that #size here is actually referring to multiple different methods;
|
128
|
+
# for name and nickname it is String#size but for phone it is Array#size.
|
116
129
|
bill.transform_values(&:size)
|
117
130
|
# => {"name" => 4, "phone" => 1, "nickname" => 5}
|
131
|
+
|
118
132
|
bill['nickname']
|
119
133
|
# => "big b"
|
120
134
|
```
|
@@ -123,13 +137,24 @@ There's plenty more JSI has to offer, but this should give you a pretty good ide
|
|
123
137
|
|
124
138
|
## Terminology and Concepts
|
125
139
|
|
126
|
-
- `JSI::Base` is the base class for each JSI class representing
|
127
|
-
- a "JSI
|
128
|
-
- a "JSI
|
140
|
+
- `JSI::Base` is the base class for each JSI schema class representing instances of JSON Schemas.
|
141
|
+
- a "JSI Schema" is a JSON Schema, instantiated as (usually) a JSI::Base described by a metaschema (see the sections on Metaschemas below). a JSI Schema is an instance of the module `JSI::Schema`.
|
142
|
+
- a "JSI Schema Module" is a module which represents one schema, dynamically created by that Schema. Instances of that schema are extended with its JSI schema module. applications may reopen these modules to add functionality to JSI instances described by a given schema.
|
143
|
+
- a "JSI schema class" is a subclass of `JSI::Base` representing one or more JSON schemas. Instances of such a class are described by all of the represented schemas. A JSI schema class includes the JSI schema module of each represented schema.
|
129
144
|
- "instance" is a term that is significantly overloaded in this space, so documentation will attempt to be clear what kind of instance is meant:
|
130
145
|
- a schema instance refers broadly to a data structure that is described by a JSON schema.
|
131
|
-
- a JSI instance (or just "a JSI") is a ruby object instantiating a JSI class.
|
132
|
-
-
|
146
|
+
- a JSI instance (or just "a JSI") is a ruby object instantiating a JSI schema class (subclass of `JSI::Base`). This wraps the content of the schema instance (see `JSI::Base#jsi_instance`), and ties it to the schemas which describe the instance (`JSI::Base#jsi_schemas`).
|
147
|
+
- "schema" refers to either a parsed JSON schema (generally a ruby Hash) or a JSI schema.
|
148
|
+
|
149
|
+
## Supported specification versions
|
150
|
+
|
151
|
+
JSI supports these JSON Schema specification versions:
|
152
|
+
|
153
|
+
| Version | `$schema` URI | JSI Schema Module |
|
154
|
+
| --- | --- | --- |
|
155
|
+
| Draft 4 | `http://json-schema.org/draft-04/schema#` | {JSI::JSONSchemaOrgDraft04} |
|
156
|
+
| Draft 6 | `http://json-schema.org/draft-06/schema#` | {JSI::JSONSchemaOrgDraft06} |
|
157
|
+
| Draft 7 | `http://json-schema.org/draft-07/schema#` | {JSI::JSONSchemaOrgDraft07} |
|
133
158
|
|
134
159
|
## JSI and Object Oriented Programming
|
135
160
|
|
@@ -160,11 +185,19 @@ bill.phone_numbers
|
|
160
185
|
|
161
186
|
Note the use of `super` - you can call to accessors defined by JSI and make your accessors act as wrappers. You can alternatively use `[]` and `[]=` with the same effect.
|
162
187
|
|
163
|
-
|
188
|
+
Working with subschemas is just about as easy as with root schemas.
|
189
|
+
|
190
|
+
You can subscript or use property accessors on a JSI schema module to refer to the schema modules of its subschemas, e.g.:
|
164
191
|
|
165
192
|
```ruby
|
166
|
-
|
167
|
-
|
193
|
+
Contact.properties['phone'].items
|
194
|
+
# => Contact.properties["phone"].items (JSI Schema Module)
|
195
|
+
```
|
196
|
+
|
197
|
+
Opening a subschema module with [`module_exec`](https://ruby-doc.org/core/Module.html#method-i-module_exec), you can add methods to instances of the subschema.
|
198
|
+
|
199
|
+
```ruby
|
200
|
+
Contact.properties['phone'].items.module_exec do
|
168
201
|
def number_with_dashes
|
169
202
|
number.split(//).join('-')
|
170
203
|
end
|
@@ -173,10 +206,24 @@ bill.phone.first.number_with_dashes
|
|
173
206
|
# => "5-5-5"
|
174
207
|
```
|
175
208
|
|
176
|
-
|
209
|
+
A recommended convention for naming subschemas is to define them in the namespace of the module of their
|
210
|
+
parent schema. The module can then be opened to add methods to the subschema's module.
|
211
|
+
|
212
|
+
```ruby
|
213
|
+
module Contact
|
214
|
+
Phone = properties['phone'].items
|
215
|
+
module Phone
|
216
|
+
def number_with_dashes
|
217
|
+
number.split(//).join('-')
|
218
|
+
end
|
219
|
+
end
|
220
|
+
end
|
221
|
+
```
|
222
|
+
|
223
|
+
However, that is only a convention, and a flat namespace works fine too.
|
177
224
|
|
178
225
|
```ruby
|
179
|
-
ContactPhone = Contact.
|
226
|
+
ContactPhone = Contact.properties['phone'].items
|
180
227
|
module ContactPhone
|
181
228
|
def number_with_dashes
|
182
229
|
number.split(//).join('-')
|
@@ -184,15 +231,35 @@ module ContactPhone
|
|
184
231
|
end
|
185
232
|
```
|
186
233
|
|
187
|
-
|
234
|
+
### A note on Classes
|
235
|
+
|
236
|
+
The classes used to instantiate JSIs are dynamically generated subclasses of JSI::Base which include the JSI Schema Module of each schema describing the given instance. These are mostly intended to be ignored: applications aren't expected to instantiate these directly (rather, `#new_jsi` on a Schema or Schema Module is intended), and they are not intended for subclassing or method definition (applications should instead define methods on a schema's {JSI::Schema#jsi_schema_module}).
|
237
|
+
|
238
|
+
## Registration
|
239
|
+
|
240
|
+
In order for references across documents (generally from a `$ref` schema keyword) to resolve, JSI provides a registry which associates URIs with schemas (or resources containing schemas). This registry is accessible on {JSI.schema_registry} and is a {JSI::SchemaRegistry}.
|
241
|
+
|
242
|
+
Schemas instantiated with `.new_schema`, and their subschemas, are automatically registered with `JSI.schema_registry` if they identify an absolute URI.
|
243
|
+
|
244
|
+
Schemas can automatically be lazily loaded by registering a block which instantiates them with {JSI::SchemaRegistry#autoload_uri} (see its documentation).
|
245
|
+
|
246
|
+
## Validation
|
247
|
+
|
248
|
+
JSI implements all required features, and many optional features, for validation according to supported JSON Schema specifications. To validate instances, see methods {JSI::Base#jsi_validate}, {JSI::Base#jsi_valid?}, {JSI::Schema#instance_validate}, {JSI::Schema#instance_valid?}.
|
249
|
+
|
250
|
+
The following optional features are not completely supported:
|
251
|
+
|
252
|
+
- The `format` keyword does not perform any validation.
|
253
|
+
- Regular expressions are interpreted by Ruby's Regexp class, whereas JSON Schema recommends interpreting these as ECMA 262 regular expressions. Certain expressions behave differently, particularly `^` and `$`.
|
254
|
+
- Keywords `contentMediaType` and `contentEncoding` do not perform validation.
|
188
255
|
|
189
256
|
## Metaschemas
|
190
257
|
|
191
258
|
A metaschema is a schema which describes schemas. Likewise, a schema is an instance of a metaschema.
|
192
259
|
|
193
|
-
In JSI, a schema is generally a JSI::Base instance whose
|
260
|
+
In JSI, a schema is generally a JSI::Base instance whose schemas include a metaschema.
|
194
261
|
|
195
|
-
A self-descriptive metaschema - most commonly one of the JSON schema draft metaschemas - is an object whose
|
262
|
+
A self-descriptive metaschema - most commonly one of the JSON schema draft metaschemas - is an object whose schemas include itself. This is instantiated in JSI as a JSI::MetaschemaNode, a special subclass of JSI::Base.
|
196
263
|
|
197
264
|
## ActiveRecord serialization
|
198
265
|
|
@@ -202,7 +269,7 @@ Let's say you're sticking to JSON types in the database - you have to do so if y
|
|
202
269
|
|
203
270
|
But if your database contains JSON, then your deserialized objects in ruby are likewise Hash / Array / basic types. You have to use subscripts instead of accessors, and you don't have any way to add methods to your data types.
|
204
271
|
|
205
|
-
JSI gives you the best of both with JSICoder. This coder dumps objects which are simple JSON types, and loads instances of a specified JSI schema. Here's an example
|
272
|
+
JSI gives you the best of both with JSICoder. This coder dumps objects which are simple JSON types, and loads instances of a specified JSI schema. Here's an example, supposing a `users` table with a JSON column `contact_info`:
|
206
273
|
|
207
274
|
```ruby
|
208
275
|
class User < ActiveRecord::Base
|
@@ -210,13 +277,13 @@ class User < ActiveRecord::Base
|
|
210
277
|
end
|
211
278
|
```
|
212
279
|
|
213
|
-
Now `user.
|
280
|
+
Now `user.contact_info` will be instantiated as a Contact JSI instance, from the JSON type in the database, with Contact's accessors, validations, and user-defined instance methods.
|
214
281
|
|
215
282
|
See the gem [`arms`](https://github.com/notEthan/arms) if you wish to serialize the dumped JSON-compatible objects further as text.
|
216
283
|
|
217
284
|
## Keying Hashes (JSON Objects)
|
218
285
|
|
219
|
-
Unlike Ruby, JSON only supports string keys. It is recommended to use strings as hash keys for all JSI instances, but JSI does not enforce this, nor does it do any key conversion.
|
286
|
+
Unlike Ruby, JSON only supports string keys. It is recommended to use strings as hash keys for all JSI instances, but JSI does not enforce this, nor does it do any key conversion. You may also use [ActiveSupport::HashWithIndifferentAccess](https://api.rubyonrails.org/classes/ActiveSupport/HashWithIndifferentAccess.html) as the instance of a JSI in order to gain the benefits that offers over a plain hash. Note that activesupport is not a dependency of jsi and would be required separately for this.
|
220
287
|
|
221
288
|
## Contributing
|
222
289
|
|
@@ -224,7 +291,7 @@ Issues and pull requests are welcome on GitHub at https://github.com/notEthan/js
|
|
224
291
|
|
225
292
|
## License
|
226
293
|
|
227
|
-
[<img align="right" src="https://github.com/notEthan/jsi/raw/
|
294
|
+
[<img align="right" src="https://github.com/notEthan/jsi/raw/v0.3.0/resources/icons/AGPL-3.0.png">](https://www.gnu.org/licenses/agpl-3.0.html)
|
228
295
|
|
229
296
|
JSI is licensed under the terms of the [GNU Affero General Public License version 3](https://www.gnu.org/licenses/agpl-3.0.html).
|
230
297
|
|