surrealist 0.1.0 → 0.1.2
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 +4 -4
- data/.gitignore +1 -0
- data/.rspec +0 -1
- data/.travis.yml +1 -0
- data/CHANGELOG.md +16 -4
- data/README.md +151 -9
- data/lib/surrealist/any.rb +4 -0
- data/lib/surrealist/{boolean.rb → bool.rb} +1 -1
- data/lib/surrealist/builder.rb +13 -25
- data/lib/surrealist/instance_methods.rb +4 -4
- data/lib/surrealist/type_helper.rb +57 -0
- data/lib/surrealist/utils.rb +69 -0
- data/lib/surrealist/version.rb +1 -1
- data/lib/surrealist.rb +11 -16
- data/surrealist.gemspec +2 -0
- metadata +21 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: cad5fa813b903c8a83c6618f48a8e5f027244346
|
|
4
|
+
data.tar.gz: 4c65f03f060c4c93ae2dd036f634bcc84ab77d3e
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 85121fc7dd2a504fe51d03337c52d2ea08784eeca7fbb150f43f047bfe9c915cff1cb813051307cff9a552ad3c564f891eadca1e8dd18e412a850b150f85cd23
|
|
7
|
+
data.tar.gz: 140e6ced9ee0c3e35b77417e12279699ab0468d7c154e9f8cf5bf89e2a73f7bb065303dc5a39013153acd1c5ca9aeea0b3dd0b477cdcde64cfd5a7f295061bd5
|
data/.gitignore
CHANGED
data/.rspec
CHANGED
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
|
@@ -1,8 +1,20 @@
|
|
|
1
|
+
# 0.1.2
|
|
2
|
+
## Added
|
|
3
|
+
* `Any` module for skipping type checks
|
|
4
|
+
* Optional `camelize` argument to convert keys to camelBacks
|
|
5
|
+
|
|
6
|
+
# 0.1.0
|
|
7
|
+
## Fixed
|
|
8
|
+
* Fix schema mutability issue
|
|
9
|
+
## Changed
|
|
10
|
+
* Change `schema` class method to `json_schema` due to compatibility issues with other gems.
|
|
11
|
+
|
|
1
12
|
# 0.0.6
|
|
2
|
-
|
|
13
|
+
## Added
|
|
14
|
+
* `build_schema` instance method that builds hash from the schema without serializing it to json.
|
|
15
|
+
## Changed
|
|
3
16
|
* Allow nil values by default.
|
|
4
17
|
* Allow nested objects.
|
|
5
18
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
* Fix schema mutability issue
|
|
19
|
+
|
|
20
|
+
|
data/README.md
CHANGED
|
@@ -8,16 +8,30 @@ A gem that provides DSL for serialization of plain old Ruby objects to JSON in a
|
|
|
8
8
|
by defining a `json_schema`. It also provides a trivial type checking in the runtime before serialization.
|
|
9
9
|
[Yard documentation](http://www.rubydoc.info/github/nesaulov/surrealist/master)
|
|
10
10
|
|
|
11
|
-
## Current status
|
|
12
|
-
In development, not yet ready for real projects.
|
|
13
11
|
|
|
14
12
|
## Motivation
|
|
15
13
|
A typical use case for this gem could be, for example, serializing a (decorated) object outside
|
|
16
14
|
of the view context. The schema is described through a hash, so you can build the structure
|
|
17
|
-
of serialized object independently of its methods and attributes
|
|
15
|
+
of serialized object independently of its methods and attributes, while also having possibility
|
|
16
|
+
to serialize nested objects and structures.
|
|
17
|
+
|
|
18
|
+
* [Installation](#installation)
|
|
19
|
+
* [Usage](#usage)
|
|
20
|
+
* [Simple example](#simple-example)
|
|
21
|
+
* [Nested structures](#nested-structures)
|
|
22
|
+
* [Nested objects](#nested-objects)
|
|
23
|
+
* [Usage with Dry::Types](#usage-with-drytypes)
|
|
24
|
+
* [Build schema](#build-schema)
|
|
25
|
+
* [Camelization](#camelization)
|
|
26
|
+
* [Bool and Any](#bool-and-any)
|
|
27
|
+
* [Type errors](#type-errors)
|
|
28
|
+
* [Undefined methods in schema](#undefined-methods-in-schema)
|
|
29
|
+
* [Other notes](#other-notes)
|
|
30
|
+
* [Contributing](#contributing)
|
|
31
|
+
* [License](#license)
|
|
18
32
|
|
|
19
|
-
## Installation
|
|
20
33
|
|
|
34
|
+
## Installation
|
|
21
35
|
Add this line to your application's Gemfile:
|
|
22
36
|
|
|
23
37
|
``` ruby
|
|
@@ -36,7 +50,7 @@ Or install it yourself as:
|
|
|
36
50
|
## Usage
|
|
37
51
|
Schema should be defined with a block that contains a hash. Every key of the schema should be
|
|
38
52
|
either a name of a method of the surrealizable object (or it's parents/mixins),
|
|
39
|
-
or - in case
|
|
53
|
+
or - in case you want to build json structure independently from object's structure - a symbol.
|
|
40
54
|
Every value of the hash should be a constant that represents a Ruby class,
|
|
41
55
|
that will be used for type-checks.
|
|
42
56
|
|
|
@@ -69,7 +83,7 @@ end
|
|
|
69
83
|
|
|
70
84
|
``` ruby
|
|
71
85
|
Person.new.surrealize
|
|
72
|
-
# =>
|
|
86
|
+
# => '{ "foo": "This is a string", "bar" :42 }'
|
|
73
87
|
```
|
|
74
88
|
|
|
75
89
|
### Nested structures
|
|
@@ -94,12 +108,133 @@ class Person
|
|
|
94
108
|
end
|
|
95
109
|
|
|
96
110
|
Person.find_by(email: 'example@email.com').surrealize
|
|
97
|
-
# =>
|
|
111
|
+
# => '{ "foo": "Some string", "name": "John Doe", "nested": { "at": { "any": 42, "level": true } } }'
|
|
98
112
|
```
|
|
99
113
|
|
|
114
|
+
### Nested objects
|
|
115
|
+
If you need to serialize nested objects and their attributes, you should
|
|
116
|
+
define a method that calls nested object:
|
|
117
|
+
|
|
118
|
+
``` ruby
|
|
119
|
+
class User
|
|
120
|
+
include Surrealist
|
|
121
|
+
|
|
122
|
+
json_schema do
|
|
123
|
+
{
|
|
124
|
+
name: String,
|
|
125
|
+
credit_card: {
|
|
126
|
+
number: Integer,
|
|
127
|
+
cvv: Integer,
|
|
128
|
+
},
|
|
129
|
+
}
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
def name
|
|
133
|
+
'John Doe'
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
def credit_card
|
|
137
|
+
# Assuming that instance of a CreditCard has methods #number and #cvv defined
|
|
138
|
+
CreditCard.find_by(holder: name)
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
User.new.surrealize
|
|
143
|
+
# => '{ "name": "John Doe", "credit_card": { "number" :1234, "cvv": 322 } }'
|
|
144
|
+
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
### Usage with Dry::Types
|
|
148
|
+
You can use `Dry::Types` for type checking. Note that Surrealist does not ship
|
|
149
|
+
with dry-types by default, so you should do the [installation and configuration](http://dry-rb.org/gems/dry-types/)
|
|
150
|
+
by yourself. All built-in features of dry-types work, so if you use, say, `Types::Coercible::String`,
|
|
151
|
+
your data will be coerced if it is able to, otherwise you will get a TypeError.
|
|
152
|
+
Assuming, that you have defined module called `Types`:
|
|
153
|
+
|
|
154
|
+
``` ruby
|
|
155
|
+
require 'dry-types'
|
|
156
|
+
|
|
157
|
+
class Car
|
|
158
|
+
include Surrealist
|
|
159
|
+
|
|
160
|
+
json_schema do
|
|
161
|
+
{
|
|
162
|
+
age: Types::Coercible::Int,
|
|
163
|
+
brand: Types::Coercible::String,
|
|
164
|
+
doors: Types::Int.optional,
|
|
165
|
+
horsepower: Types::Strict::Int.constrained(gteq: 20),
|
|
166
|
+
fuel_system: Types::Any,
|
|
167
|
+
previous_owner: Types::String,
|
|
168
|
+
}
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
def age;
|
|
172
|
+
'7';
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
def previous_owner;
|
|
176
|
+
'John Doe';
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
def horsepower;
|
|
180
|
+
140;
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
def brand;
|
|
184
|
+
'Toyota';
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
def doors; end
|
|
188
|
+
|
|
189
|
+
def fuel_system;
|
|
190
|
+
'Direct injection';
|
|
191
|
+
end
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
Car.new.surrealize
|
|
195
|
+
# => '{ "age": 7, "brand": "Toyota", "doors": null, "horsepower": 140, "fuel_system": "Direct injection", "previous_owner": "John Doe" }'
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
### Build schema
|
|
199
|
+
If you don't need to dump the hash to json, you can use `#build_schema`
|
|
200
|
+
method on the instance. It calculates values and checks types, but returns
|
|
201
|
+
a hash instead of a JSON string. From the previous example:
|
|
202
|
+
|
|
203
|
+
``` ruby
|
|
204
|
+
Car.new.build_schema
|
|
205
|
+
# => { age: 7, brand: "Toyota", doors: nil, horsepower: 140, fuel_system: "Direct injection", previous_owner: "John Doe" }
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
### Camelization
|
|
209
|
+
If you need to have keys in camelBack, you can pass optional `camelize` argument
|
|
210
|
+
to `#surrealize`. From the previous example:
|
|
211
|
+
|
|
212
|
+
``` ruby
|
|
213
|
+
Car.new.surrealize(camelize: true)
|
|
214
|
+
# => '{ "age": 7, "brand": "Toyota", "doors": null, "horsepower": 140, "fuelSystem": "Direct injection", "previousOwner": "John Doe" }'
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
### Bool and Any
|
|
218
|
+
If you have a parameter that is of boolean type, or if you don't care about the type, you
|
|
219
|
+
can use `Bool` and `Any` respectively.
|
|
220
|
+
|
|
221
|
+
``` ruby
|
|
222
|
+
class User
|
|
223
|
+
include Surrealist
|
|
224
|
+
|
|
225
|
+
json_schema do
|
|
226
|
+
{
|
|
227
|
+
age: Any,
|
|
228
|
+
admin: Bool,
|
|
229
|
+
}
|
|
230
|
+
end
|
|
231
|
+
end
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
|
|
100
235
|
### Type Errors
|
|
101
236
|
|
|
102
|
-
`Surrealist::InvalidTypeError` is thrown if types mismatch.
|
|
237
|
+
`Surrealist::InvalidTypeError` is thrown if types (and dry-types) mismatch.
|
|
103
238
|
|
|
104
239
|
``` ruby
|
|
105
240
|
class CreditCard
|
|
@@ -109,7 +244,9 @@ class CreditCard
|
|
|
109
244
|
{ number: Integer }
|
|
110
245
|
end
|
|
111
246
|
|
|
112
|
-
def number
|
|
247
|
+
def number
|
|
248
|
+
'string'
|
|
249
|
+
end
|
|
113
250
|
end
|
|
114
251
|
|
|
115
252
|
CreditCard.new.surrealize
|
|
@@ -134,6 +271,11 @@ Car.new.surrealize
|
|
|
134
271
|
# => Surrealist::UndefinedMethodError: undefined method `weight' for #<Car:0x007f9bc1dc7fa8>. You have probably defined a key in the schema that doesn't have a corresponding method.
|
|
135
272
|
```
|
|
136
273
|
|
|
274
|
+
### Other notes
|
|
275
|
+
* nil values are allowed by default, so if you have, say, `age: String`, but the actual value is nil,
|
|
276
|
+
type check will be passed. If you want to be strict about `nil`s consider using `Dry::Types`.
|
|
277
|
+
* Surrealist requires ruby of version 2.2 and higher.
|
|
278
|
+
|
|
137
279
|
## Contributing
|
|
138
280
|
|
|
139
281
|
Bug reports and pull requests are welcome on GitHub at https://github.com/nesaulov/surrealist.
|
data/lib/surrealist/builder.rb
CHANGED
|
@@ -15,13 +15,15 @@ module Surrealist
|
|
|
15
15
|
#
|
|
16
16
|
# @return [Hash] a hash that will be dumped into JSON.
|
|
17
17
|
def call(schema:, instance:)
|
|
18
|
-
schema.each do |
|
|
19
|
-
if
|
|
20
|
-
parse_hash(hash:
|
|
18
|
+
schema.each do |schema_key, schema_value|
|
|
19
|
+
if schema_value.is_a?(Hash)
|
|
20
|
+
parse_hash(hash: schema_value, schema: schema, instance: instance, key: schema_key)
|
|
21
21
|
else
|
|
22
|
-
type
|
|
23
|
-
|
|
24
|
-
assign_value(method:
|
|
22
|
+
type = schema_value
|
|
23
|
+
schema_value = instance.is_a?(Hash) ? instance[schema_key] : instance.send(schema_key)
|
|
24
|
+
assign_value(method: schema_key, value: schema_value, type: type) do |coerced_value|
|
|
25
|
+
schema[schema_key] = coerced_value
|
|
26
|
+
end
|
|
25
27
|
end
|
|
26
28
|
end
|
|
27
29
|
rescue NoMethodError => e
|
|
@@ -85,8 +87,8 @@ module Surrealist
|
|
|
85
87
|
parse_hash(hash: value, schema: hash, instance: result, key: key)
|
|
86
88
|
else
|
|
87
89
|
type = value
|
|
88
|
-
assign_value(method: key, value: result, type: type) do
|
|
89
|
-
schema[method] = schema[method].merge(key =>
|
|
90
|
+
assign_value(method: key, value: result, type: type) do |coerced_value|
|
|
91
|
+
schema[method] = schema[method].merge(key => coerced_value)
|
|
90
92
|
end
|
|
91
93
|
end
|
|
92
94
|
end
|
|
@@ -101,28 +103,14 @@ module Surrealist
|
|
|
101
103
|
#
|
|
102
104
|
# @return [Hash] schema
|
|
103
105
|
def assign_value(method:, value:, type:, &_block)
|
|
104
|
-
if
|
|
105
|
-
|
|
106
|
+
if TypeHelper.valid_type?(value: value, type: type)
|
|
107
|
+
value = TypeHelper.coerce(type: type, value: value)
|
|
108
|
+
yield value
|
|
106
109
|
else
|
|
107
110
|
raise Surrealist::InvalidTypeError,
|
|
108
111
|
"Wrong type for key `#{method}`. Expected #{type}, got #{value.class}."
|
|
109
112
|
end
|
|
110
113
|
end
|
|
111
|
-
|
|
112
|
-
# Checks if value returned from a method is an instance of type class specified
|
|
113
|
-
# in schema or NilClass.
|
|
114
|
-
#
|
|
115
|
-
# @param [any] value value returned from a method.
|
|
116
|
-
# @param [Class] type class representing data type.
|
|
117
|
-
#
|
|
118
|
-
# @return [boolean]
|
|
119
|
-
def type_check_passed?(value:, type:)
|
|
120
|
-
if type == Boolean
|
|
121
|
-
[true, false].include?(value)
|
|
122
|
-
else
|
|
123
|
-
value.nil? || value.is_a?(type)
|
|
124
|
-
end
|
|
125
|
-
end
|
|
126
114
|
end
|
|
127
115
|
end
|
|
128
116
|
end
|
|
@@ -4,13 +4,13 @@ module Surrealist
|
|
|
4
4
|
# Instance methods that are included to the object's class
|
|
5
5
|
module InstanceMethods
|
|
6
6
|
# Invokes +Surrealist+'s class method +surrealize+
|
|
7
|
-
def surrealize
|
|
8
|
-
Surrealist.surrealize(self)
|
|
7
|
+
def surrealize(camelize: false)
|
|
8
|
+
Surrealist.surrealize(self, camelize: camelize)
|
|
9
9
|
end
|
|
10
10
|
|
|
11
11
|
# Invokes +Surrealist+'s class method +build_schema+
|
|
12
|
-
def build_schema
|
|
13
|
-
Surrealist.build_schema(self)
|
|
12
|
+
def build_schema(camelize: false)
|
|
13
|
+
Surrealist.build_schema(self, camelize: camelize)
|
|
14
14
|
end
|
|
15
15
|
end
|
|
16
16
|
end
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Surrealist
|
|
4
|
+
# Service class for type checking
|
|
5
|
+
class TypeHelper
|
|
6
|
+
DRY_TYPE_CLASS = 'Dry::Types'
|
|
7
|
+
|
|
8
|
+
class << self
|
|
9
|
+
# Checks if value returned from a method is an instance of type class specified
|
|
10
|
+
# in schema or NilClass.
|
|
11
|
+
#
|
|
12
|
+
# @param [any] value value returned from a method.
|
|
13
|
+
# @param [Class] type class representing data type.
|
|
14
|
+
#
|
|
15
|
+
# @return [boolean]
|
|
16
|
+
def valid_type?(value:, type:)
|
|
17
|
+
return true if type == Any
|
|
18
|
+
|
|
19
|
+
if type == Bool
|
|
20
|
+
[true, false].include?(value)
|
|
21
|
+
elsif dry_type?(type)
|
|
22
|
+
type.try(value).success?
|
|
23
|
+
else
|
|
24
|
+
value.nil? || value.is_a?(type)
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# Coerces value is it should be coerced
|
|
29
|
+
#
|
|
30
|
+
# @param [any] value value that will be coerced
|
|
31
|
+
# @param [Class] type class representing data type
|
|
32
|
+
#
|
|
33
|
+
# @return [any] coerced value
|
|
34
|
+
def coerce(value:, type:)
|
|
35
|
+
return value unless dry_type?(type)
|
|
36
|
+
return value if type.try(value).input == value
|
|
37
|
+
|
|
38
|
+
type[value]
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
private
|
|
42
|
+
|
|
43
|
+
# Checks if type is an instance of dry-type
|
|
44
|
+
#
|
|
45
|
+
# @param [Object] type type to be checked
|
|
46
|
+
#
|
|
47
|
+
# @return [Boolean] is type an instance of dry-type
|
|
48
|
+
def dry_type?(type)
|
|
49
|
+
if type.respond_to?(:primitive) || type.class.name.nil?
|
|
50
|
+
true
|
|
51
|
+
else
|
|
52
|
+
type.class.name.match(DRY_TYPE_CLASS)
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Surrealist
|
|
4
|
+
# A helper class to camelize hash keys and deep copy objects
|
|
5
|
+
class Utils
|
|
6
|
+
class << self
|
|
7
|
+
# Deep copies the schema hash.
|
|
8
|
+
#
|
|
9
|
+
# @param [Object] hash object to be copied
|
|
10
|
+
#
|
|
11
|
+
# @return [Object] a copied object
|
|
12
|
+
def deep_copy(hash)
|
|
13
|
+
hash.each_with_object({}) do |(key, value), new|
|
|
14
|
+
new[key] = value.is_a?(Hash) ? deep_copy(value) : value
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# Converts hash's keys to camelCase
|
|
19
|
+
#
|
|
20
|
+
# @param [Hash] hash a hash to be camelized
|
|
21
|
+
#
|
|
22
|
+
# @return [Hash] camelized hash
|
|
23
|
+
def camelize_hash(hash)
|
|
24
|
+
if hash.is_a?(Hash)
|
|
25
|
+
Hash[hash.map { |k, v| [camelize_key(k, false), camelize_hash(v)] }]
|
|
26
|
+
else
|
|
27
|
+
hash
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
private
|
|
32
|
+
|
|
33
|
+
# Converts symbol to string and camelizes it
|
|
34
|
+
#
|
|
35
|
+
# @param [String | Symbol] key a key to be camelized
|
|
36
|
+
#
|
|
37
|
+
# @param [Boolean] first_upper should the first letter be capitalized
|
|
38
|
+
#
|
|
39
|
+
# @return [String | Symbol] camelized key of a hash
|
|
40
|
+
def camelize_key(key, first_upper = true)
|
|
41
|
+
if key.is_a? Symbol
|
|
42
|
+
camelize(key.to_s, first_upper).to_sym
|
|
43
|
+
elsif key.is_a? String
|
|
44
|
+
camelize(key, first_upper)
|
|
45
|
+
else
|
|
46
|
+
key
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# Camelizes a word
|
|
51
|
+
#
|
|
52
|
+
# @param [String] snake_word a word to be camelized
|
|
53
|
+
#
|
|
54
|
+
# @param [Boolean] first_upper should the first letter be capitalized
|
|
55
|
+
#
|
|
56
|
+
# @return [String] camelized string
|
|
57
|
+
def camelize(snake_word, first_upper = true)
|
|
58
|
+
if first_upper
|
|
59
|
+
snake_word.to_s
|
|
60
|
+
.gsub(/(?:^|_)([^_\s]+)/) { Regexp.last_match[1].capitalize }
|
|
61
|
+
else
|
|
62
|
+
parts = snake_word.split('_', 2)
|
|
63
|
+
parts[0] << camelize(parts[1]) if parts.size > 1
|
|
64
|
+
parts[0] || ''
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
data/lib/surrealist/version.rb
CHANGED
data/lib/surrealist.rb
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
require 'surrealist/class_methods'
|
|
4
|
+
require 'surrealist/instance_methods'
|
|
5
|
+
require 'surrealist/bool'
|
|
6
|
+
require 'surrealist/any'
|
|
7
|
+
require 'surrealist/utils'
|
|
8
|
+
require 'surrealist/type_helper'
|
|
6
9
|
require 'json'
|
|
7
10
|
|
|
8
11
|
# Main module that provides the +json_schema+ class method and +surrealize+ instance method.
|
|
@@ -64,8 +67,8 @@ module Surrealist
|
|
|
64
67
|
# User.new.surrealize
|
|
65
68
|
# # => "{\"name\":\"Nikita\",\"age\":23}"
|
|
66
69
|
# # For more examples see README
|
|
67
|
-
def self.surrealize(instance)
|
|
68
|
-
::JSON.dump(build_schema(instance))
|
|
70
|
+
def self.surrealize(instance, camelize:)
|
|
71
|
+
::JSON.dump(build_schema(instance, camelize: camelize))
|
|
69
72
|
end
|
|
70
73
|
|
|
71
74
|
# Builds hash from schema provided in the object's class and type-checks the values.
|
|
@@ -106,23 +109,15 @@ module Surrealist
|
|
|
106
109
|
# User.new.build_schema
|
|
107
110
|
# # => { name: 'Nikita', age: 23 }
|
|
108
111
|
# # For more examples see README
|
|
109
|
-
def self.build_schema(instance)
|
|
112
|
+
def self.build_schema(instance, camelize:)
|
|
110
113
|
schema = instance.class.instance_variable_get('@__surrealist_schema')
|
|
111
114
|
|
|
112
115
|
if schema.nil?
|
|
113
116
|
raise Surrealist::UnknownSchemaError, "Can't serialize #{instance.class} - no schema was provided."
|
|
114
117
|
end
|
|
115
118
|
|
|
119
|
+
hash = Builder.call(schema: Surrealist::Utils.deep_copy(schema), instance: instance)
|
|
116
120
|
|
|
117
|
-
|
|
118
|
-
end
|
|
119
|
-
|
|
120
|
-
# Deep copies the schema hash.
|
|
121
|
-
#
|
|
122
|
-
# @param [Object] obj object to be coopied
|
|
123
|
-
#
|
|
124
|
-
# @return [Object] a copied object
|
|
125
|
-
def self.deep_copy(obj)
|
|
126
|
-
Marshal.load(Marshal.dump(obj))
|
|
121
|
+
camelize ? Surrealist::Utils.camelize_hash(hash) : hash
|
|
127
122
|
end
|
|
128
123
|
end
|
data/surrealist.gemspec
CHANGED
|
@@ -22,9 +22,11 @@ Gem::Specification.new do |spec|
|
|
|
22
22
|
spec.bindir = 'exe'
|
|
23
23
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
|
24
24
|
spec.require_paths = ['lib']
|
|
25
|
+
spec.required_ruby_version = '>= 2.2.0'
|
|
25
26
|
|
|
26
27
|
spec.add_development_dependency 'bundler', '~> 1.15'
|
|
27
28
|
spec.add_development_dependency 'rake', '~> 12.0'
|
|
28
29
|
spec.add_development_dependency 'pry', '~> 0.11'
|
|
29
30
|
spec.add_development_dependency 'rspec', '~> 3.6'
|
|
31
|
+
spec.add_development_dependency 'dry-types', '~> 0.12'
|
|
30
32
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: surrealist
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Nikita Esaulov
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2017-
|
|
11
|
+
date: 2017-10-02 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: bundler
|
|
@@ -66,6 +66,20 @@ dependencies:
|
|
|
66
66
|
- - "~>"
|
|
67
67
|
- !ruby/object:Gem::Version
|
|
68
68
|
version: '3.6'
|
|
69
|
+
- !ruby/object:Gem::Dependency
|
|
70
|
+
name: dry-types
|
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
|
72
|
+
requirements:
|
|
73
|
+
- - "~>"
|
|
74
|
+
- !ruby/object:Gem::Version
|
|
75
|
+
version: '0.12'
|
|
76
|
+
type: :development
|
|
77
|
+
prerelease: false
|
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
79
|
+
requirements:
|
|
80
|
+
- - "~>"
|
|
81
|
+
- !ruby/object:Gem::Version
|
|
82
|
+
version: '0.12'
|
|
69
83
|
description: A gem that provides DSL for serialization of plain old Ruby objects to
|
|
70
84
|
JSON in a declarative style by defining a `schema`. It also provides a trivial type
|
|
71
85
|
checking in the runtime before serialization.
|
|
@@ -84,11 +98,14 @@ files:
|
|
|
84
98
|
- README.md
|
|
85
99
|
- bin/console
|
|
86
100
|
- lib/surrealist.rb
|
|
87
|
-
- lib/surrealist/
|
|
101
|
+
- lib/surrealist/any.rb
|
|
102
|
+
- lib/surrealist/bool.rb
|
|
88
103
|
- lib/surrealist/builder.rb
|
|
89
104
|
- lib/surrealist/class_methods.rb
|
|
90
105
|
- lib/surrealist/instance_methods.rb
|
|
91
106
|
- lib/surrealist/schema_definer.rb
|
|
107
|
+
- lib/surrealist/type_helper.rb
|
|
108
|
+
- lib/surrealist/utils.rb
|
|
92
109
|
- lib/surrealist/version.rb
|
|
93
110
|
- surrealist.gemspec
|
|
94
111
|
homepage: https://github.com/nesaulov/surrealist
|
|
@@ -103,7 +120,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
103
120
|
requirements:
|
|
104
121
|
- - ">="
|
|
105
122
|
- !ruby/object:Gem::Version
|
|
106
|
-
version:
|
|
123
|
+
version: 2.2.0
|
|
107
124
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
108
125
|
requirements:
|
|
109
126
|
- - ">="
|