shale 0.2.2 → 0.4.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.
Files changed (66) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +33 -0
  3. data/README.md +366 -8
  4. data/exe/shaleb +123 -0
  5. data/lib/shale/adapter/json.rb +7 -2
  6. data/lib/shale/adapter/nokogiri.rb +48 -12
  7. data/lib/shale/adapter/ox.rb +28 -4
  8. data/lib/shale/adapter/rexml.rb +56 -13
  9. data/lib/shale/attribute.rb +7 -1
  10. data/lib/shale/error.rb +12 -0
  11. data/lib/shale/mapper.rb +17 -15
  12. data/lib/shale/mapping/descriptor/dict.rb +57 -0
  13. data/lib/shale/mapping/descriptor/xml.rb +43 -0
  14. data/lib/shale/mapping/descriptor/xml_namespace.rb +37 -0
  15. data/lib/shale/mapping/{key_value.rb → dict.rb} +8 -6
  16. data/lib/shale/mapping/validator.rb +51 -0
  17. data/lib/shale/mapping/xml.rb +86 -15
  18. data/lib/shale/schema/json_compiler/boolean.rb +21 -0
  19. data/lib/shale/schema/json_compiler/date.rb +21 -0
  20. data/lib/shale/schema/json_compiler/float.rb +21 -0
  21. data/lib/shale/schema/json_compiler/integer.rb +21 -0
  22. data/lib/shale/schema/json_compiler/object.rb +85 -0
  23. data/lib/shale/schema/json_compiler/property.rb +70 -0
  24. data/lib/shale/schema/json_compiler/string.rb +21 -0
  25. data/lib/shale/schema/json_compiler/time.rb +21 -0
  26. data/lib/shale/schema/json_compiler/utils.rb +52 -0
  27. data/lib/shale/schema/json_compiler/value.rb +13 -0
  28. data/lib/shale/schema/json_compiler.rb +333 -0
  29. data/lib/shale/schema/json_generator/base.rb +41 -0
  30. data/lib/shale/schema/json_generator/boolean.rb +23 -0
  31. data/lib/shale/schema/json_generator/collection.rb +39 -0
  32. data/lib/shale/schema/json_generator/date.rb +23 -0
  33. data/lib/shale/schema/json_generator/float.rb +23 -0
  34. data/lib/shale/schema/json_generator/integer.rb +23 -0
  35. data/lib/shale/schema/json_generator/object.rb +40 -0
  36. data/lib/shale/schema/json_generator/ref.rb +28 -0
  37. data/lib/shale/schema/json_generator/schema.rb +59 -0
  38. data/lib/shale/schema/json_generator/string.rb +23 -0
  39. data/lib/shale/schema/json_generator/time.rb +23 -0
  40. data/lib/shale/schema/json_generator/value.rb +23 -0
  41. data/lib/shale/schema/json_generator.rb +165 -0
  42. data/lib/shale/schema/xml_generator/attribute.rb +41 -0
  43. data/lib/shale/schema/xml_generator/complex_type.rb +70 -0
  44. data/lib/shale/schema/xml_generator/element.rb +55 -0
  45. data/lib/shale/schema/xml_generator/import.rb +46 -0
  46. data/lib/shale/schema/xml_generator/ref_attribute.rb +37 -0
  47. data/lib/shale/schema/xml_generator/ref_element.rb +39 -0
  48. data/lib/shale/schema/xml_generator/schema.rb +121 -0
  49. data/lib/shale/schema/xml_generator/typed_attribute.rb +46 -0
  50. data/lib/shale/schema/xml_generator/typed_element.rb +46 -0
  51. data/lib/shale/schema/xml_generator.rb +315 -0
  52. data/lib/shale/schema.rb +70 -0
  53. data/lib/shale/type/boolean.rb +2 -2
  54. data/lib/shale/type/composite.rb +78 -72
  55. data/lib/shale/type/date.rb +35 -2
  56. data/lib/shale/type/float.rb +2 -2
  57. data/lib/shale/type/integer.rb +2 -2
  58. data/lib/shale/type/string.rb +2 -2
  59. data/lib/shale/type/time.rb +35 -2
  60. data/lib/shale/type/{base.rb → value.rb} +18 -7
  61. data/lib/shale/utils.rb +18 -2
  62. data/lib/shale/version.rb +1 -1
  63. data/lib/shale.rb +10 -10
  64. data/shale.gemspec +6 -2
  65. metadata +53 -13
  66. data/lib/shale/mapping/base.rb +0 -32
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative 'base'
3
+ require_relative 'value'
4
4
 
5
5
  module Shale
6
6
  module Type
@@ -8,7 +8,7 @@ module Shale
8
8
  # It serves as a base type class for @see Shale::Mapper
9
9
  #
10
10
  # @api private
11
- class Composite < Base
11
+ class Composite < Value
12
12
  class << self
13
13
  %i[hash json yaml].each do |format|
14
14
  class_eval(<<-RUBY, __FILE__, __LINE__ + 1)
@@ -19,7 +19,7 @@ module Shale
19
19
  # @return [Shale::Mapper]
20
20
  #
21
21
  # @api public
22
- def out_of_#{format}(hash)
22
+ def of_#{format}(hash)
23
23
  instance = new
24
24
 
25
25
  mapping_keys = #{format}_mapping.keys
@@ -28,25 +28,22 @@ module Shale
28
28
  mapping = mapping_keys[key]
29
29
  next unless mapping
30
30
 
31
- if mapping.is_a?(Hash)
32
- instance.send(mapping[:from], value)
31
+ if mapping.method_from
32
+ instance.send(mapping.method_from, value)
33
33
  else
34
- attribute = attributes[mapping]
34
+ attribute = attributes[mapping.attribute]
35
35
  next unless attribute
36
36
 
37
37
  if value.nil?
38
- instance.public_send("\#{attribute.name}=", nil)
39
- next
40
- end
41
-
42
- if attribute.collection?
38
+ instance.send(attribute.setter, nil)
39
+ elsif attribute.collection?
43
40
  [*value].each do |val|
44
- val = val ? attribute.type.out_of_#{format}(val) : val
45
- instance.public_send(attribute.name) << attribute.type.cast(val)
41
+ val = val ? attribute.type.of_#{format}(val) : val
42
+ instance.send(attribute.name) << attribute.type.cast(val)
46
43
  end
47
44
  else
48
- val = attribute.type.out_of_#{format}(value)
49
- instance.public_send("\#{attribute.name}=", val)
45
+ val = attribute.type.of_#{format}(value)
46
+ instance.send(attribute.setter, val)
50
47
  end
51
48
  end
52
49
  end
@@ -56,7 +53,7 @@ module Shale
56
53
 
57
54
  # Convert Object to Hash using Hash/JSON/YAML mapping
58
55
  #
59
- # @param [Shale::Type::Base] instance Object to convert
56
+ # @param [Shale::Mapper] instance Object to convert
60
57
  #
61
58
  # @return [Hash]
62
59
  #
@@ -64,24 +61,23 @@ module Shale
64
61
  def as_#{format}(instance)
65
62
  hash = {}
66
63
 
67
- instance.class.#{format}_mapping.keys.each do |key, attr|
68
- if attr.is_a?(Hash)
69
- hash[key] = instance.send(attr[:to])
64
+ instance.class.#{format}_mapping.keys.each_value do |mapping|
65
+ if mapping.method_to
66
+ hash[mapping.name] = instance.send(mapping.method_to)
70
67
  else
71
- attribute = instance.class.attributes[attr]
68
+ attribute = instance.class.attributes[mapping.attribute]
72
69
  next unless attribute
73
70
 
74
- value = instance.public_send(attribute.name)
71
+ value = instance.send(attribute.name)
75
72
 
76
73
  if value.nil?
77
- hash[key] = nil
78
- next
79
- end
80
-
81
- if attribute.collection?
82
- hash[key] = [*value].map { |v| v ? attribute.type.as_#{format}(v) : v }
74
+ hash[mapping.name] = nil
75
+ elsif attribute.collection?
76
+ hash[mapping.name] = [*value].map do |v|
77
+ v ? attribute.type.as_#{format}(v) : v
78
+ end
83
79
  else
84
- hash[key] = attribute.type.as_#{format}(value)
80
+ hash[mapping.name] = attribute.type.as_#{format}(value)
85
81
  end
86
82
  end
87
83
  end
@@ -91,7 +87,7 @@ module Shale
91
87
  RUBY
92
88
  end
93
89
 
94
- alias from_hash out_of_hash
90
+ alias from_hash of_hash
95
91
 
96
92
  alias to_hash as_hash
97
93
 
@@ -103,18 +99,19 @@ module Shale
103
99
  #
104
100
  # @api public
105
101
  def from_json(json)
106
- out_of_json(Shale.json_adapter.load(json))
102
+ of_json(Shale.json_adapter.load(json))
107
103
  end
108
104
 
109
105
  # Convert Object to JSON
110
106
  #
111
- # @param [Shale::Type::Base] instance Object to convert
107
+ # @param [Shale::Mapper] instance Object to convert
108
+ # @param [Array<Symbol>] options
112
109
  #
113
110
  # @return [String]
114
111
  #
115
112
  # @api public
116
- def to_json(instance)
117
- Shale.json_adapter.dump(as_json(instance))
113
+ def to_json(instance, *options)
114
+ Shale.json_adapter.dump(as_json(instance), *options)
118
115
  end
119
116
 
120
117
  # Convert YAML to Object
@@ -125,12 +122,12 @@ module Shale
125
122
  #
126
123
  # @api public
127
124
  def from_yaml(yaml)
128
- out_of_yaml(Shale.yaml_adapter.load(yaml))
125
+ of_yaml(Shale.yaml_adapter.load(yaml))
129
126
  end
130
127
 
131
128
  # Convert Object to YAML
132
129
  #
133
- # @param [Shale::Type::Base] instance Object to convert
130
+ # @param [Shale::Mapper] instance Object to convert
134
131
  #
135
132
  # @return [String]
136
133
  #
@@ -146,23 +143,23 @@ module Shale
146
143
  # @return [Shale::Mapper]
147
144
  #
148
145
  # @api public
149
- def out_of_xml(element)
146
+ def of_xml(element)
150
147
  instance = new
151
148
 
152
149
  element.attributes.each do |key, value|
153
150
  mapping = xml_mapping.attributes[key.to_s]
154
151
  next unless mapping
155
152
 
156
- if mapping.is_a?(Hash)
157
- instance.send(mapping[:from], value)
153
+ if mapping.method_from
154
+ instance.send(mapping.method_from, value)
158
155
  else
159
- attribute = attributes[mapping]
156
+ attribute = attributes[mapping.attribute]
160
157
  next unless attribute
161
158
 
162
159
  if attribute.collection?
163
- instance.public_send(attribute.name) << attribute.type.cast(value)
160
+ instance.send(attribute.name) << attribute.type.cast(value)
164
161
  else
165
- instance.public_send("#{attribute.name}=", value)
162
+ instance.send(attribute.setter, value)
166
163
  end
167
164
  end
168
165
  end
@@ -171,7 +168,7 @@ module Shale
171
168
  attribute = attributes[xml_mapping.content]
172
169
 
173
170
  if attribute
174
- instance.public_send("#{attribute.name}=", attribute.type.out_of_xml(element))
171
+ instance.send(attribute.setter, attribute.type.of_xml(element))
175
172
  end
176
173
  end
177
174
 
@@ -179,17 +176,17 @@ module Shale
179
176
  mapping = xml_mapping.elements[node.name]
180
177
  next unless mapping
181
178
 
182
- if mapping.is_a?(Hash)
183
- instance.send(mapping[:from], node)
179
+ if mapping.method_from
180
+ instance.send(mapping.method_from, node)
184
181
  else
185
- attribute = attributes[mapping]
182
+ attribute = attributes[mapping.attribute]
186
183
  next unless attribute
187
184
 
188
185
  if attribute.collection?
189
- value = attribute.type.out_of_xml(node)
190
- instance.public_send(attribute.name) << attribute.type.cast(value)
186
+ value = attribute.type.of_xml(node)
187
+ instance.send(attribute.name) << attribute.type.cast(value)
191
188
  else
192
- instance.public_send("#{attribute.name}=", attribute.type.out_of_xml(node))
189
+ instance.send(attribute.setter, attribute.type.of_xml(node))
193
190
  end
194
191
  end
195
192
  end
@@ -205,12 +202,12 @@ module Shale
205
202
  #
206
203
  # @api public
207
204
  def from_xml(xml)
208
- out_of_xml(Shale.xml_adapter.load(xml))
205
+ of_xml(Shale.xml_adapter.load(xml))
209
206
  end
210
207
 
211
208
  # Convert Object to XML document
212
209
  #
213
- # @param [Shale::Type::Base] instance Object to convert
210
+ # @param [Shale::Mapper] instance Object to convert
214
211
  # @param [String, nil] node_name XML node name
215
212
  # @param [Shale::Adapter::<xml adapter>::Document, nil] doc Object to convert
216
213
  #
@@ -220,23 +217,25 @@ module Shale
220
217
  def as_xml(instance, node_name = nil, doc = nil)
221
218
  unless doc
222
219
  doc = Shale.xml_adapter.create_document
223
- doc.add_element(doc.doc, as_xml(instance, instance.class.xml_mapping.root, doc))
220
+ doc.add_element(doc.doc, as_xml(instance, xml_mapping.prefixed_root, doc))
224
221
  return doc.doc
225
222
  end
226
223
 
227
224
  element = doc.create_element(node_name)
225
+ doc.add_namespace(xml_mapping.default_namespace.prefix, xml_mapping.default_namespace.name)
228
226
 
229
- xml_mapping.attributes.each do |xml_attr, obj_attr|
230
- if obj_attr.is_a?(Hash)
231
- instance.send(obj_attr[:to], element, doc)
227
+ xml_mapping.attributes.each_value do |mapping|
228
+ if mapping.method_to
229
+ instance.send(mapping.method_to, element, doc)
232
230
  else
233
- attribute = instance.class.attributes[obj_attr]
231
+ attribute = instance.class.attributes[mapping.attribute]
234
232
  next unless attribute
235
233
 
236
- value = instance.public_send(attribute.name)
234
+ value = instance.send(attribute.name)
237
235
  next if value.nil?
238
236
 
239
- doc.add_attribute(element, xml_attr, value)
237
+ doc.add_namespace(mapping.namespace.prefix, mapping.namespace.name)
238
+ doc.add_attribute(element, mapping.prefixed_name, value)
240
239
  end
241
240
  end
242
241
 
@@ -244,28 +243,30 @@ module Shale
244
243
  attribute = instance.class.attributes[xml_mapping.content]
245
244
 
246
245
  if attribute
247
- value = instance.public_send(attribute.name)
246
+ value = instance.send(attribute.name)
248
247
  doc.add_text(element, value.to_s) if value
249
248
  end
250
249
  end
251
250
 
252
- xml_mapping.elements.each do |xml_name, obj_attr|
253
- if obj_attr.is_a?(Hash)
254
- instance.send(obj_attr[:to], element, doc)
251
+ xml_mapping.elements.each_value do |mapping|
252
+ if mapping.method_to
253
+ instance.send(mapping.method_to, element, doc)
255
254
  else
256
- attribute = instance.class.attributes[obj_attr]
255
+ attribute = instance.class.attributes[mapping.attribute]
257
256
  next unless attribute
258
257
 
259
- value = instance.public_send(attribute.name)
258
+ value = instance.send(attribute.name)
260
259
  next if value.nil?
261
260
 
261
+ doc.add_namespace(mapping.namespace.prefix, mapping.namespace.name)
262
+
262
263
  if attribute.collection?
263
264
  [*value].each do |v|
264
265
  next if v.nil?
265
- doc.add_element(element, attribute.type.as_xml(v, xml_name, doc))
266
+ doc.add_element(element, attribute.type.as_xml(v, mapping.prefixed_name, doc))
266
267
  end
267
268
  else
268
- doc.add_element(element, attribute.type.as_xml(value, xml_name, doc))
269
+ doc.add_element(element, attribute.type.as_xml(value, mapping.prefixed_name, doc))
269
270
  end
270
271
  end
271
272
  end
@@ -275,13 +276,14 @@ module Shale
275
276
 
276
277
  # Convert Object to XML
277
278
  #
278
- # @param [Shale::Type::Base] instance Object to convert
279
+ # @param [Shale::Mapper] instance Object to convert
280
+ # @param [Array<Symbol>] options
279
281
  #
280
282
  # @return [String]
281
283
  #
282
284
  # @api public
283
- def to_xml(instance)
284
- Shale.xml_adapter.dump(as_xml(instance))
285
+ def to_xml(instance, *options)
286
+ Shale.xml_adapter.dump(as_xml(instance), *options)
285
287
  end
286
288
  end
287
289
 
@@ -296,11 +298,13 @@ module Shale
296
298
 
297
299
  # Convert Object to JSON
298
300
  #
301
+ # @param [Array<Symbol>] options
302
+ #
299
303
  # @return [String]
300
304
  #
301
305
  # @api public
302
- def to_json
303
- self.class.to_json(self)
306
+ def to_json(*options)
307
+ self.class.to_json(self, *options)
304
308
  end
305
309
 
306
310
  # Convert Object to YAML
@@ -314,11 +318,13 @@ module Shale
314
318
 
315
319
  # Convert Object to XML
316
320
  #
321
+ # @param [Array<Symbol>] options
322
+ #
317
323
  # @return [String]
318
324
  #
319
325
  # @api public
320
- def to_xml
321
- self.class.to_xml(self)
326
+ def to_xml(*options)
327
+ self.class.to_xml(self, *options)
322
328
  end
323
329
  end
324
330
  end
@@ -1,14 +1,14 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'date'
4
- require_relative 'base'
4
+ require_relative 'value'
5
5
 
6
6
  module Shale
7
7
  module Type
8
8
  # Cast value to Date
9
9
  #
10
10
  # @api public
11
- class Date < Base
11
+ class Date < Value
12
12
  # @param [any] value Value to cast
13
13
  #
14
14
  # @return [Date, nil]
@@ -24,6 +24,39 @@ module Shale
24
24
  value
25
25
  end
26
26
  end
27
+
28
+ # Use ISO 8601 format in JSON document
29
+ #
30
+ # @param [Date] value
31
+ #
32
+ # @return [String]
33
+ #
34
+ # @api private
35
+ def self.as_json(value)
36
+ value&.iso8601
37
+ end
38
+
39
+ # Use ISO 8601 format in YAML document
40
+ #
41
+ # @param [Date] value
42
+ #
43
+ # @return [String]
44
+ #
45
+ # @api private
46
+ def self.as_yaml(value)
47
+ value&.iso8601
48
+ end
49
+
50
+ # Use ISO 8601 format in XML document
51
+ #
52
+ # @param [Date] value Value to convert to XML
53
+ #
54
+ # @return [String]
55
+ #
56
+ # @api private
57
+ def self.as_xml_value(value)
58
+ value&.iso8601
59
+ end
27
60
  end
28
61
  end
29
62
  end
@@ -1,13 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative 'base'
3
+ require_relative 'value'
4
4
 
5
5
  module Shale
6
6
  module Type
7
7
  # Cast value to Float
8
8
  #
9
9
  # @api public
10
- class Float < Base
10
+ class Float < Value
11
11
  # @param [#to_f, String, nil] value Value to cast
12
12
  #
13
13
  # @return [Float, nil]
@@ -1,13 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative 'base'
3
+ require_relative 'value'
4
4
 
5
5
  module Shale
6
6
  module Type
7
7
  # Cast value to Integer
8
8
  #
9
9
  # @api public
10
- class Integer < Base
10
+ class Integer < Value
11
11
  # @param [#to_i, nil] value Value to cast
12
12
  #
13
13
  # @return [Integer, nil]
@@ -1,13 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative 'base'
3
+ require_relative 'value'
4
4
 
5
5
  module Shale
6
6
  module Type
7
7
  # Cast value to String
8
8
  #
9
9
  # @api public
10
- class String < Base
10
+ class String < Value
11
11
  # @param [#to_s, nil] value Value to cast
12
12
  #
13
13
  # @return [String, nil]
@@ -1,14 +1,14 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'time'
4
- require_relative 'base'
4
+ require_relative 'value'
5
5
 
6
6
  module Shale
7
7
  module Type
8
8
  # Cast value to Time
9
9
  #
10
10
  # @api public
11
- class Time < Base
11
+ class Time < Value
12
12
  # @param [any] value Value to cast
13
13
  #
14
14
  # @return [Time, nil]
@@ -24,6 +24,39 @@ module Shale
24
24
  value
25
25
  end
26
26
  end
27
+
28
+ # Use ISO 8601 format in JSON document
29
+ #
30
+ # @param [Time] value
31
+ #
32
+ # @return [String]
33
+ #
34
+ # @api private
35
+ def self.as_json(value)
36
+ value&.iso8601
37
+ end
38
+
39
+ # Use ISO 8601 format in YAML document
40
+ #
41
+ # @param [Time] value
42
+ #
43
+ # @return [String]
44
+ #
45
+ # @api private
46
+ def self.as_yaml(value)
47
+ value&.iso8601
48
+ end
49
+
50
+ # Use ISO 8601 format in XML document
51
+ #
52
+ # @param [Time] value Value to convert to XML
53
+ #
54
+ # @return [String]
55
+ #
56
+ # @api private
57
+ def self.as_xml_value(value)
58
+ value&.iso8601
59
+ end
27
60
  end
28
61
  end
29
62
  end
@@ -5,12 +5,12 @@ module Shale
5
5
  # Base class for all types
6
6
  #
7
7
  # @example
8
- # class MyType < Shale::Type::Base
8
+ # class MyType < Shale::Type::Value
9
9
  # ... overwrite methods as needed
10
10
  # end
11
11
  #
12
12
  # @api public
13
- class Base
13
+ class Value
14
14
  class << self
15
15
  # Cast raw value to a type. Base form just returns whatever it receives
16
16
  #
@@ -30,7 +30,7 @@ module Shale
30
30
  # @return [any]
31
31
  #
32
32
  # @api private
33
- def out_of_hash(value)
33
+ def of_hash(value)
34
34
  value
35
35
  end
36
36
 
@@ -52,7 +52,7 @@ module Shale
52
52
  # @return [any]
53
53
  #
54
54
  # @api private
55
- def out_of_json(value)
55
+ def of_json(value)
56
56
  value
57
57
  end
58
58
 
@@ -74,7 +74,7 @@ module Shale
74
74
  # @return [any]
75
75
  #
76
76
  # @api private
77
- def out_of_yaml(value)
77
+ def of_yaml(value)
78
78
  value
79
79
  end
80
80
 
@@ -96,20 +96,31 @@ module Shale
96
96
  # @return [String]
97
97
  #
98
98
  # @api private
99
- def out_of_xml(node)
99
+ def of_xml(node)
100
100
  node.text
101
101
  end
102
102
 
103
103
  # Convert value to form accepted by XML document
104
104
  #
105
105
  # @param [#to_s] value Value to convert to XML
106
+ #
107
+ # @return [String]
108
+ #
109
+ # @api private
110
+ def as_xml_value(value)
111
+ value.to_s
112
+ end
113
+
114
+ # Convert value to XML element
115
+ #
116
+ # @param [#to_s] value Value to convert to XML
106
117
  # @param [String] name Name of the element
107
118
  # @param [Shale::Adapter::<XML adapter>::Document] doc Document
108
119
  #
109
120
  # @api private
110
121
  def as_xml(value, name, doc)
111
122
  element = doc.create_element(name)
112
- doc.add_text(element, value.to_s)
123
+ doc.add_text(element, as_xml_value(value))
113
124
  element
114
125
  end
115
126
  end
data/lib/shale/utils.rb CHANGED
@@ -11,15 +11,31 @@ module Shale
11
11
  #
12
12
  # @example
13
13
  # Shale::Utils.underscore('FooBar') # => foo_bar
14
- # Shale::Utils.underscore('Namespace::FooBar') # => namespace:foo_bar
14
+ # Shale::Utils.underscore('Namespace::FooBar') # => foo_bar
15
15
  #
16
16
  # @api private
17
17
  def self.underscore(word)
18
18
  word
19
- .gsub('::', ':')
19
+ .split('::')
20
+ .last
20
21
  .gsub(/([A-Z\d]+)([A-Z][a-z])/, '\1_\2')
21
22
  .gsub(/([a-z\d])([A-Z])/, '\1_\2')
22
23
  .downcase
23
24
  end
25
+
26
+ # Return value or nil if value is empty
27
+ #
28
+ # @param [String] value
29
+ #
30
+ # @example
31
+ # Shale::Utils.presence('FooBar') # => FooBar
32
+ # Shale::Utils.presence('') # => nil
33
+ #
34
+ # @api private
35
+ def self.presence(value)
36
+ return nil unless value
37
+ return nil if value.empty?
38
+ value
39
+ end
24
40
  end
25
41
  end
data/lib/shale/version.rb CHANGED
@@ -2,5 +2,5 @@
2
2
 
3
3
  module Shale
4
4
  # @api private
5
- VERSION = '0.2.2'
5
+ VERSION = '0.4.0'
6
6
  end
data/lib/shale.rb CHANGED
@@ -2,16 +2,16 @@
2
2
 
3
3
  require 'yaml'
4
4
 
5
- require 'shale/mapper'
6
- require 'shale/adapter/json'
7
- require 'shale/adapter/rexml'
8
- require 'shale/type/boolean'
9
- require 'shale/type/date'
10
- require 'shale/type/float'
11
- require 'shale/type/integer'
12
- require 'shale/type/string'
13
- require 'shale/type/time'
14
- require 'shale/version'
5
+ require_relative 'shale/mapper'
6
+ require_relative 'shale/adapter/json'
7
+ require_relative 'shale/adapter/rexml'
8
+ require_relative 'shale/type/boolean'
9
+ require_relative 'shale/type/date'
10
+ require_relative 'shale/type/float'
11
+ require_relative 'shale/type/integer'
12
+ require_relative 'shale/type/string'
13
+ require_relative 'shale/type/time'
14
+ require_relative 'shale/version'
15
15
 
16
16
  # Main library namespace
17
17
  #
data/shale.gemspec CHANGED
@@ -10,17 +10,21 @@ Gem::Specification.new do |spec|
10
10
 
11
11
  spec.summary = 'Ruby object mapper and serializer for XML, JSON and YAML.'
12
12
  spec.description = 'Ruby object mapper and serializer for XML, JSON and YAML.'
13
- spec.homepage = 'https://github.com/kgiszczak/shale'
13
+ spec.homepage = 'https://shalerb.org'
14
14
  spec.license = 'MIT'
15
15
 
16
16
  spec.metadata['allowed_push_host'] = 'https://rubygems.org'
17
17
 
18
- spec.metadata['homepage_uri'] = 'https://github.com/kgiszczak/shale'
18
+ spec.metadata['homepage_uri'] = 'https://shalerb.org'
19
19
  spec.metadata['source_code_uri'] = 'https://github.com/kgiszczak/shale'
20
20
  spec.metadata['changelog_uri'] = 'https://github.com/kgiszczak/shale/blob/master/CHANGELOG.md'
21
21
  spec.metadata['bug_tracker_uri'] = 'https://github.com/kgiszczak/shale/issues'
22
22
 
23
23
  spec.files = Dir['CHANGELOG.md', 'LICENSE.txt', 'README.md', 'shale.gemspec', 'lib/**/*']
24
24
  spec.require_paths = ['lib']
25
+
26
+ spec.bindir = 'exe'
27
+ spec.executables = 'shaleb'
28
+
25
29
  spec.required_ruby_version = '>= 2.6.0'
26
30
  end