surrealist 0.1.2 → 0.1.4

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
  SHA1:
3
- metadata.gz: cad5fa813b903c8a83c6618f48a8e5f027244346
4
- data.tar.gz: 4c65f03f060c4c93ae2dd036f634bcc84ab77d3e
3
+ metadata.gz: 712012011eaaceb220f8811228de4b07c6e08460
4
+ data.tar.gz: 5ed1ef86483b6dd864a8769359443c7f760e1ae2
5
5
  SHA512:
6
- metadata.gz: 85121fc7dd2a504fe51d03337c52d2ea08784eeca7fbb150f43f047bfe9c915cff1cb813051307cff9a552ad3c564f891eadca1e8dd18e412a850b150f85cd23
7
- data.tar.gz: 140e6ced9ee0c3e35b77417e12279699ab0468d7c154e9f8cf5bf89e2a73f7bb065303dc5a39013153acd1c5ca9aeea0b3dd0b477cdcde64cfd5a7f295061bd5
6
+ metadata.gz: b15fda40fbc90382e61703564c4e7a386c521036b60227e902df8e6fd1216c933d1281ac4dc5305f0b641475ebc83187b61354550a603e086026bc0de94d0330
7
+ data.tar.gz: dc9d2a1a70f6696f5dec95214125b7fe9677ff5c19e6aa9561318127f05b30ea60b0e0dcc694436ac9313879d9fd98e4e23824532ed1f9723534dedc3daa1734
data/CHANGELOG.md CHANGED
@@ -1,11 +1,19 @@
1
+ # 0.1.4
2
+ ## Added
3
+ * Optional `include_root` argument to wrap schema in a root key. [#15](https://github.com/nesaulov/surrealist/pull/15)
4
+ ## Fixed
5
+ * Performance of schema cloning.
6
+ ## Changed
7
+ * `Boolean` module renamed to `Bool`.
8
+
1
9
  # 0.1.2
2
10
  ## Added
3
- * `Any` module for skipping type checks
4
- * Optional `camelize` argument to convert keys to camelBacks
11
+ * `Any` module for skipping type checks.
12
+ * Optional `camelize` argument to convert keys to camelBacks.
5
13
 
6
14
  # 0.1.0
7
15
  ## Fixed
8
- * Fix schema mutability issue
16
+ * Fix schema mutability issue.
9
17
  ## Changed
10
18
  * Change `schema` class method to `json_schema` due to compatibility issues with other gems.
11
19
 
data/README.md CHANGED
@@ -4,6 +4,8 @@
4
4
  [![Inline docs](http://inch-ci.org/github/nesaulov/surrealist.svg?branch=master)](http://inch-ci.org/github/nesaulov/surrealist)
5
5
  [![Gem Version](https://badge.fury.io/rb/surrealist.svg)](https://rubygems.org/gems/surrealist)
6
6
 
7
+ ![Surrealist](surrealist-icon.png)
8
+
7
9
  A gem that provides DSL for serialization of plain old Ruby objects to JSON in a declarative style
8
10
  by defining a `json_schema`. It also provides a trivial type checking in the runtime before serialization.
9
11
  [Yard documentation](http://www.rubydoc.info/github/nesaulov/surrealist/master)
@@ -13,7 +15,7 @@ by defining a `json_schema`. It also provides a trivial type checking in the run
13
15
  A typical use case for this gem could be, for example, serializing a (decorated) object outside
14
16
  of the view context. The schema is described through a hash, so you can build the structure
15
17
  of serialized object independently of its methods and attributes, while also having possibility
16
- to serialize nested objects and structures.
18
+ to serialize nested objects and structures. [Introductory blogpost.](https://medium.com/@billikota/introducing-surrealist-a-gem-to-serialize-ruby-objects-according-to-a-defined-schema-6ca7e550628d)
17
19
 
18
20
  * [Installation](#installation)
19
21
  * [Usage](#usage)
@@ -23,11 +25,14 @@ to serialize nested objects and structures.
23
25
  * [Usage with Dry::Types](#usage-with-drytypes)
24
26
  * [Build schema](#build-schema)
25
27
  * [Camelization](#camelization)
28
+ * [Include root](#include-root)
26
29
  * [Bool and Any](#bool-and-any)
27
30
  * [Type errors](#type-errors)
28
31
  * [Undefined methods in schema](#undefined-methods-in-schema)
29
32
  * [Other notes](#other-notes)
33
+ * [Roadmap](#roadmap)
30
34
  * [Contributing](#contributing)
35
+ * [Credits](#credits)
31
36
  * [License](#license)
32
37
 
33
38
 
@@ -63,17 +68,14 @@ class Person
63
68
  include Surrealist
64
69
 
65
70
  json_schema do
66
- {
67
- foo: String,
68
- bar: Integer,
69
- }
71
+ { name: String, age: Integer }
70
72
  end
71
73
 
72
- def foo
73
- 'This is a string'
74
+ def name
75
+ 'John Doe'
74
76
  end
75
77
 
76
- def bar
78
+ def age
77
79
  42
78
80
  end
79
81
  end
@@ -83,7 +85,7 @@ end
83
85
 
84
86
  ``` ruby
85
87
  Person.new.surrealize
86
- # => '{ "foo": "This is a string", "bar" :42 }'
88
+ # => '{ "name": "John Doe", "age": 42 }'
87
89
  ```
88
90
 
89
91
  ### Nested structures
@@ -140,7 +142,7 @@ class User
140
142
  end
141
143
 
142
144
  User.new.surrealize
143
- # => '{ "name": "John Doe", "credit_card": { "number" :1234, "cvv": 322 } }'
145
+ # => '{ "name": "John Doe", "credit_card": { "number": 1234, "cvv": 322 } }'
144
146
 
145
147
  ```
146
148
 
@@ -149,7 +151,7 @@ You can use `Dry::Types` for type checking. Note that Surrealist does not ship
149
151
  with dry-types by default, so you should do the [installation and configuration](http://dry-rb.org/gems/dry-types/)
150
152
  by yourself. All built-in features of dry-types work, so if you use, say, `Types::Coercible::String`,
151
153
  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`:
154
+ Assuming that you have defined module called `Types`:
153
155
 
154
156
  ``` ruby
155
157
  require 'dry-types'
@@ -169,25 +171,25 @@ class Car
169
171
  end
170
172
 
171
173
  def age;
172
- '7';
174
+ '7'
173
175
  end
174
176
 
175
177
  def previous_owner;
176
- 'John Doe';
178
+ 'John Doe'
177
179
  end
178
180
 
179
181
  def horsepower;
180
- 140;
182
+ 140
181
183
  end
182
184
 
183
185
  def brand;
184
- 'Toyota';
186
+ 'Toyota'
185
187
  end
186
188
 
187
189
  def doors; end
188
190
 
189
191
  def fuel_system;
190
- 'Direct injection';
192
+ 'Direct injection'
191
193
  end
192
194
  end
193
195
 
@@ -207,13 +209,54 @@ Car.new.build_schema
207
209
 
208
210
  ### Camelization
209
211
  If you need to have keys in camelBack, you can pass optional `camelize` argument
210
- to `#surrealize`. From the previous example:
212
+ to `#surrealize or #build_schema`. From the previous example:
211
213
 
212
214
  ``` ruby
213
215
  Car.new.surrealize(camelize: true)
214
216
  # => '{ "age": 7, "brand": "Toyota", "doors": null, "horsepower": 140, "fuelSystem": "Direct injection", "previousOwner": "John Doe" }'
215
217
  ```
216
218
 
219
+ ### Include root
220
+ If you want to wrap the resulting JSON into a root key, you can pass optional `include_root` argument
221
+ to `#surrealize` or `#build_schema`. The root key in this case will be taken from the class name of the
222
+ surrealizable object.
223
+ ``` ruby
224
+ class Cat
225
+ include Surrealist
226
+
227
+ json_schema do
228
+ { weight: String }
229
+ end
230
+
231
+ def weight
232
+ '3 kilos'
233
+ end
234
+ end
235
+
236
+ Cat.new.surrealize(include_root: true)
237
+ # => '{ "cat": { "weight": "3 kilos" } }'
238
+ ```
239
+ With nested classes the last namespace will be taken as root key:
240
+ ``` ruby
241
+ class Animal
242
+ class Dog
243
+ include Surrealist
244
+
245
+ json_schema do
246
+ { breed: String }
247
+ end
248
+
249
+ def breed
250
+ 'Collie'
251
+ end
252
+ end
253
+ end
254
+
255
+ Animal::Dog.new.surrealize(include_root: true)
256
+ # => '{ "dog": { "breed": "Collie" } }'
257
+ ```
258
+ Nesting namespaces are [yet to be implemented.](https://github.com/nesaulov/surrealist/issues/14)
259
+
217
260
  ### Bool and Any
218
261
  If you have a parameter that is of boolean type, or if you don't care about the type, you
219
262
  can use `Bool` and `Any` respectively.
@@ -274,14 +317,22 @@ Car.new.surrealize
274
317
  ### Other notes
275
318
  * nil values are allowed by default, so if you have, say, `age: String`, but the actual value is nil,
276
319
  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.
320
+ * Surrealist requires MRI ruby of version 2.2 and higher.
278
321
 
279
- ## Contributing
322
+ ## Roadmap
323
+ Here is a list of features that are not implemented yet (contributions are welcome):
324
+ * [ActiveRecord_Relation serialization](https://github.com/nesaulov/surrealist/issues/13)
325
+ * [Collection serialization](https://github.com/nesaulov/surrealist/issues/12)
326
+ * [Delegating serialization to parent class](https://github.com/nesaulov/surrealist/issues/11)
327
+ * [Having nested namespaces being surrealized](https://github.com/nesaulov/surrealist/issues/14)
280
328
 
329
+ ## Contributing
281
330
  Bug reports and pull requests are welcome on GitHub at https://github.com/nesaulov/surrealist.
282
331
  This project is intended to be a safe, welcoming space for collaboration, and contributors are expected
283
332
  to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
284
333
 
285
- ## License
334
+ ## Credits
335
+ The icon was created by [Simon Child from Noun Project](https://thenounproject.com/term/salvador-dali/124566/) and is published under [Creative Commons License](https://creativecommons.org/licenses/by/3.0/us/)
286
336
 
337
+ ## License
287
338
  The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
@@ -0,0 +1,131 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Surrealist
4
+ # A helper class to camelize, wrap and deeply copy hashes.
5
+ class HashUtils
6
+ class << self
7
+ # Deeply copies the schema hash and wraps it if there is a need to.
8
+ #
9
+ # @param [Object] hash object to be copied.
10
+ # @param [Boolean] include_root optional argument for including root in the hash.
11
+ # @param [Boolean] camelize optional argument for camelizing the root key of the hash.
12
+ # @param [String] klass instance's class name.
13
+ #
14
+ # @return [Object] a copied object
15
+ def deep_copy(hash:, include_root: false, camelize: false, klass: false)
16
+ return copy_hash(hash) unless include_root
17
+ raise_unknown_root! if include_root && !klass
18
+
19
+ actual_class = extract_class(klass)
20
+ root_key = camelize ? camelize(actual_class, false).to_sym : underscore(actual_class).to_sym
21
+ object = Hash[root_key => {}]
22
+ copy_hash(hash, wrapper: object[root_key])
23
+
24
+ object
25
+ end
26
+
27
+ # Converts hash's keys to camelBack keys.
28
+ #
29
+ # @param [Hash] hash a hash to be camelized.
30
+ #
31
+ # @return [Hash] camelized hash.
32
+ def camelize_hash(hash)
33
+ if hash.is_a?(Hash)
34
+ Hash[hash.map { |k, v| [camelize_key(k, false), camelize_hash(v)] }]
35
+ else
36
+ hash
37
+ end
38
+ end
39
+
40
+ private
41
+
42
+ # Goes through the hash recursively and deeply copies it.
43
+ #
44
+ # @param [Hash] hash the hash to be copied.
45
+ # @param [Hash] wrapper the wrapper of the resulting hash.
46
+ #
47
+ # @return [Hash] deeply copied hash.
48
+ def copy_hash(hash, wrapper: {})
49
+ hash.each_with_object(wrapper) do |(key, value), new|
50
+ new[key] = value.is_a?(Hash) ? copy_hash(value) : value
51
+ end
52
+ end
53
+
54
+ # Converts symbol to string and camelizes it.
55
+ #
56
+ # @param [String | Symbol] key a key to be camelized.
57
+ # @param [Boolean] first_upper should the first letter be capitalized.
58
+ #
59
+ # @return [String | Symbol] camelized key of a hash.
60
+ def camelize_key(key, first_upper = true)
61
+ if key.is_a? Symbol
62
+ camelize(key.to_s, first_upper).to_sym
63
+ elsif key.is_a? String
64
+ camelize(key, first_upper)
65
+ else
66
+ key
67
+ end
68
+ end
69
+
70
+ # Camelizes a string.
71
+ #
72
+ # @param [String] snake_string a string to be camelized.
73
+ # @param [Boolean] first_upper should the first letter be capitalized.
74
+ #
75
+ # @return [String] camelized string.
76
+ def camelize(snake_string, first_upper = true)
77
+ if first_upper
78
+ snake_string.to_s
79
+ .gsub(/(?:^|_)([^_\s]+)/) { Regexp.last_match[1].capitalize }
80
+ else
81
+ parts = snake_string.split('_', 2)
82
+ parts[0] << camelize(parts[1]) if parts.size > 1
83
+ parts[0] || ''
84
+ end
85
+ end
86
+
87
+ # Clones a string and converts first character to lower case.
88
+ #
89
+ # @param [String] string a string to be cloned.
90
+ #
91
+ # @return [String] new string with lower cased first character.
92
+ def uncapitalize(string)
93
+ str = string.dup
94
+ str[0] = str[0].downcase
95
+ str
96
+ end
97
+
98
+ # Converts a string to snake_case.
99
+ #
100
+ # @param [String] string a string to be underscored.
101
+ #
102
+ # @return [String] underscored string.
103
+ def underscore(string)
104
+ string.gsub('::', '_')
105
+ .gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
106
+ .gsub(/([a-z\d])([A-Z])/, '\1_\2')
107
+ .tr('-', '_')
108
+ .downcase
109
+ end
110
+
111
+ # Extract last class from a namespace.
112
+ #
113
+ # @param [String] string full namespace
114
+ #
115
+ # @example Extract class
116
+ # extract_class('Animal::Dog::Collie') # => 'Collie'
117
+ #
118
+ # @return [String] extracted class
119
+ def extract_class(string)
120
+ uncapitalize(string.split('::').last)
121
+ end
122
+
123
+ # Raises Surrealist::UnknownRootError if class's name is unknown.
124
+ #
125
+ # @raise Surrealist::UnknownRootError
126
+ def raise_unknown_root!
127
+ raise Surrealist::UnknownRootError, "Can't wrap schema in root key - class name was not passed"
128
+ end
129
+ end
130
+ end
131
+ 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(camelize: false)
8
- Surrealist.surrealize(self, camelize: camelize)
7
+ def surrealize(camelize: false, include_root: false)
8
+ Surrealist.surrealize(instance: self, camelize: camelize, include_root: include_root)
9
9
  end
10
10
 
11
11
  # Invokes +Surrealist+'s class method +build_schema+
12
- def build_schema(camelize: false)
13
- Surrealist.build_schema(self, camelize: camelize)
12
+ def build_schema(camelize: false, include_root: false)
13
+ Surrealist.build_schema(instance: self, camelize: camelize, include_root: include_root)
14
14
  end
15
15
  end
16
16
  end
@@ -3,6 +3,7 @@
3
3
  module Surrealist
4
4
  # Service class for type checking
5
5
  class TypeHelper
6
+ # Dry-types class matcher
6
7
  DRY_TYPE_CLASS = 'Dry::Types'
7
8
 
8
9
  class << self
@@ -2,5 +2,5 @@
2
2
 
3
3
  module Surrealist
4
4
  # Defines the version of Surrealist
5
- VERSION = '0.1.2'
5
+ VERSION = '0.1.4'
6
6
  end
data/lib/surrealist.rb CHANGED
@@ -4,7 +4,7 @@ require 'surrealist/class_methods'
4
4
  require 'surrealist/instance_methods'
5
5
  require 'surrealist/bool'
6
6
  require 'surrealist/any'
7
- require 'surrealist/utils'
7
+ require 'surrealist/hash_utils'
8
8
  require 'surrealist/type_helper'
9
9
  require 'json'
10
10
 
@@ -22,102 +22,126 @@ module Surrealist
22
22
  # Error class for failed type-checks.
23
23
  class InvalidTypeError < TypeError; end
24
24
 
25
- # @param [Class] base class to include/extend +Surrealist+.
26
- def self.included(base)
27
- base.extend(Surrealist::ClassMethods)
28
- base.include(Surrealist::InstanceMethods)
29
- end
30
-
31
- # Dumps the object's methods corresponding to the schema
32
- # provided in the object's class and type-checks the values.
33
- #
34
- # @param [Object] instance of a class that has +Surrealist+ included.
35
- #
36
- # @return [String] a json-formatted string corresponding to the schema
37
- # provided in the object's class. Values will be taken from the return values
38
- # of appropriate methods from the object.
39
- #
40
- # @raise +Surrealist::UnknownSchemaError+ if no schema was provided in the object's class.
41
- #
42
- # @raise +Surrealist::InvalidTypeError+ if type-check failed at some point.
43
- #
44
- # @raise +Surrealist::UndefinedMethodError+ if a key defined in the schema
45
- # does not have a corresponding method on the object.
46
- #
47
- # @example Define a schema and surrealize the object
48
- # class User
49
- # include Surrealist
50
- #
51
- # json_schema do
52
- # {
53
- # name: String,
54
- # age: Integer,
55
- # }
56
- # end
57
- #
58
- # def name
59
- # 'Nikita'
60
- # end
61
- #
62
- # def age
63
- # 23
64
- # end
65
- # end
66
- #
67
- # User.new.surrealize
68
- # # => "{\"name\":\"Nikita\",\"age\":23}"
69
- # # For more examples see README
70
- def self.surrealize(instance, camelize:)
71
- ::JSON.dump(build_schema(instance, camelize: camelize))
72
- end
25
+ # Error class for undefined root keys for schema wrapping.
26
+ class UnknownRootError < RuntimeError; end
73
27
 
74
- # Builds hash from schema provided in the object's class and type-checks the values.
75
- #
76
- # @param [Object] instance of a class that has +Surrealist+ included.
77
- #
78
- # @return [Hash] a hash corresponding to the schema
79
- # provided in the object's class. Values will be taken from the return values
80
- # of appropriate methods from the object.
81
- #
82
- # @raise +Surrealist::UnknownSchemaError+ if no schema was provided in the object's class.
83
- #
84
- # @raise +Surrealist::InvalidTypeError+ if type-check failed at some point.
85
- #
86
- # @raise +Surrealist::UndefinedMethodError+ if a key defined in the schema
87
- # does not have a corresponding method on the object.
88
- #
89
- # @example Define a schema and surrealize the object
90
- # class User
91
- # include Surrealist
92
- #
93
- # json_schema do
94
- # {
95
- # name: String,
96
- # age: Integer,
97
- # }
98
- # end
99
- #
100
- # def name
101
- # 'Nikita'
102
- # end
103
- #
104
- # def age
105
- # 23
106
- # end
107
- # end
108
- #
109
- # User.new.build_schema
110
- # # => { name: 'Nikita', age: 23 }
111
- # # For more examples see README
112
- def self.build_schema(instance, camelize:)
113
- schema = instance.class.instance_variable_get('@__surrealist_schema')
28
+ class << self
29
+ # @param [Class] base class to include/extend +Surrealist+.
30
+ def included(base)
31
+ base.extend(Surrealist::ClassMethods)
32
+ base.include(Surrealist::InstanceMethods)
33
+ end
114
34
 
115
- if schema.nil?
116
- raise Surrealist::UnknownSchemaError, "Can't serialize #{instance.class} - no schema was provided."
35
+ # Dumps the object's methods corresponding to the schema
36
+ # provided in the object's class and type-checks the values.
37
+ #
38
+ # @param [Object] instance of a class that has +Surrealist+ included.
39
+ # @param [Boolean] camelize optional argument for converting hash to camelBack.
40
+ # @param [Boolean] include_root optional argument for having the root key of the resulting hash
41
+ # as instance's class name.
42
+ #
43
+ # @return [String] a json-formatted string corresponding to the schema
44
+ # provided in the object's class. Values will be taken from the return values
45
+ # of appropriate methods from the object.
46
+ #
47
+ # @raise +Surrealist::UnknownSchemaError+ if no schema was provided in the object's class.
48
+ #
49
+ # @raise +Surrealist::InvalidTypeError+ if type-check failed at some point.
50
+ #
51
+ # @raise +Surrealist::UndefinedMethodError+ if a key defined in the schema
52
+ # does not have a corresponding method on the object.
53
+ #
54
+ # @example Define a schema and surrealize the object
55
+ # class User
56
+ # include Surrealist
57
+ #
58
+ # json_schema do
59
+ # {
60
+ # name: String,
61
+ # age: Integer,
62
+ # }
63
+ # end
64
+ #
65
+ # def name
66
+ # 'Nikita'
67
+ # end
68
+ #
69
+ # def age
70
+ # 23
71
+ # end
72
+ # end
73
+ #
74
+ # User.new.surrealize
75
+ # # => "{\"name\":\"Nikita\",\"age\":23}"
76
+ # # For more examples see README
77
+ def surrealize(instance:, camelize:, include_root:)
78
+ ::JSON.dump(build_schema(instance: instance, camelize: camelize, include_root: include_root))
117
79
  end
118
80
 
119
- hash = Builder.call(schema: Surrealist::Utils.deep_copy(schema), instance: instance)
81
+ # Builds hash from schema provided in the object's class and type-checks the values.
82
+ #
83
+ # @param [Object] instance of a class that has +Surrealist+ included.
84
+ # @param [Boolean] camelize optional argument for converting hash to camelBack.
85
+ # @param [Boolean] include_root optional argument for having the root key of the resulting hash
86
+ # as instance's class name.
87
+ #
88
+ # @return [Hash] a hash corresponding to the schema
89
+ # provided in the object's class. Values will be taken from the return values
90
+ # of appropriate methods from the object.
91
+ #
92
+ # @raise +Surrealist::UnknownSchemaError+ if no schema was provided in the object's class.
93
+ #
94
+ # @raise +Surrealist::InvalidTypeError+ if type-check failed at some point.
95
+ #
96
+ # @raise +Surrealist::UndefinedMethodError+ if a key defined in the schema
97
+ # does not have a corresponding method on the object.
98
+ #
99
+ # @example Define a schema and surrealize the object
100
+ # class User
101
+ # include Surrealist
102
+ #
103
+ # json_schema do
104
+ # {
105
+ # name: String,
106
+ # age: Integer,
107
+ # }
108
+ # end
109
+ #
110
+ # def name
111
+ # 'Nikita'
112
+ # end
113
+ #
114
+ # def age
115
+ # 23
116
+ # end
117
+ # end
118
+ #
119
+ # User.new.build_schema
120
+ # # => { name: 'Nikita', age: 23 }
121
+ # # For more examples see README
122
+ def build_schema(instance:, camelize:, include_root:)
123
+ schema = instance.class.instance_variable_get('@__surrealist_schema')
124
+
125
+ raise_unknown_schema!(instance) if schema.nil?
120
126
 
121
- camelize ? Surrealist::Utils.camelize_hash(hash) : hash
127
+ normalized_schema = Surrealist::HashUtils.deep_copy(
128
+ hash: schema,
129
+ klass: instance.class.name,
130
+ camelize: camelize,
131
+ include_root: include_root,
132
+ )
133
+
134
+ hash = Builder.call(schema: normalized_schema, instance: instance)
135
+ camelize ? Surrealist::HashUtils.camelize_hash(hash) : hash
136
+ end
137
+
138
+ # Raises Surrealist::UnknownSchemaError
139
+ #
140
+ # @param [Object] instance instance of the class without schema defined.
141
+ #
142
+ # @raise Surrealist::UnknownSchemaError
143
+ def raise_unknown_schema!(instance)
144
+ raise Surrealist::UnknownSchemaError, "Can't serialize #{instance.class} - no schema was provided."
145
+ end
122
146
  end
123
147
  end
Binary file
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.2
4
+ version: 0.1.4
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-10-02 00:00:00.000000000 Z
11
+ date: 2017-10-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -102,11 +102,12 @@ files:
102
102
  - lib/surrealist/bool.rb
103
103
  - lib/surrealist/builder.rb
104
104
  - lib/surrealist/class_methods.rb
105
+ - lib/surrealist/hash_utils.rb
105
106
  - lib/surrealist/instance_methods.rb
106
107
  - lib/surrealist/schema_definer.rb
107
108
  - lib/surrealist/type_helper.rb
108
- - lib/surrealist/utils.rb
109
109
  - lib/surrealist/version.rb
110
+ - surrealist-icon.png
110
111
  - surrealist.gemspec
111
112
  homepage: https://github.com/nesaulov/surrealist
112
113
  licenses:
@@ -1,69 +0,0 @@
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