shale 0.2.1 → 0.3.1

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 (54) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +24 -0
  3. data/README.md +274 -7
  4. data/exe/shaleb +75 -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 +1 -1
  10. data/lib/shale/error.rb +6 -0
  11. data/lib/shale/mapper.rb +11 -11
  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/base.rb +41 -0
  19. data/lib/shale/schema/json/boolean.rb +23 -0
  20. data/lib/shale/schema/json/collection.rb +39 -0
  21. data/lib/shale/schema/json/date.rb +23 -0
  22. data/lib/shale/schema/json/float.rb +23 -0
  23. data/lib/shale/schema/json/integer.rb +23 -0
  24. data/lib/shale/schema/json/object.rb +37 -0
  25. data/lib/shale/schema/json/ref.rb +28 -0
  26. data/lib/shale/schema/json/schema.rb +57 -0
  27. data/lib/shale/schema/json/string.rb +23 -0
  28. data/lib/shale/schema/json/time.rb +23 -0
  29. data/lib/shale/schema/json.rb +165 -0
  30. data/lib/shale/schema/xml/attribute.rb +41 -0
  31. data/lib/shale/schema/xml/complex_type.rb +67 -0
  32. data/lib/shale/schema/xml/element.rb +55 -0
  33. data/lib/shale/schema/xml/import.rb +46 -0
  34. data/lib/shale/schema/xml/ref_attribute.rb +37 -0
  35. data/lib/shale/schema/xml/ref_element.rb +39 -0
  36. data/lib/shale/schema/xml/schema.rb +121 -0
  37. data/lib/shale/schema/xml/typed_attribute.rb +46 -0
  38. data/lib/shale/schema/xml/typed_element.rb +46 -0
  39. data/lib/shale/schema/xml.rb +316 -0
  40. data/lib/shale/schema.rb +47 -0
  41. data/lib/shale/type/boolean.rb +2 -2
  42. data/lib/shale/type/composite.rb +67 -56
  43. data/lib/shale/type/date.rb +35 -2
  44. data/lib/shale/type/float.rb +2 -2
  45. data/lib/shale/type/integer.rb +2 -2
  46. data/lib/shale/type/string.rb +2 -2
  47. data/lib/shale/type/time.rb +35 -2
  48. data/lib/shale/type/{base.rb → value.rb} +18 -7
  49. data/lib/shale/utils.rb +18 -2
  50. data/lib/shale/version.rb +1 -1
  51. data/lib/shale.rb +10 -10
  52. data/shale.gemspec +6 -2
  53. metadata +41 -13
  54. 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,10 +28,10 @@ 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?
@@ -41,11 +41,11 @@ module Shale
41
41
 
42
42
  if attribute.collection?
43
43
  [*value].each do |val|
44
- val = val ? attribute.type.out_of_#{format}(val) : val
44
+ val = val ? attribute.type.of_#{format}(val) : val
45
45
  instance.public_send(attribute.name) << attribute.type.cast(val)
46
46
  end
47
47
  else
48
- val = attribute.type.out_of_#{format}(value)
48
+ val = attribute.type.of_#{format}(value)
49
49
  instance.public_send("\#{attribute.name}=", val)
50
50
  end
51
51
  end
@@ -56,7 +56,7 @@ module Shale
56
56
 
57
57
  # Convert Object to Hash using Hash/JSON/YAML mapping
58
58
  #
59
- # @param [Shale::Type::Base] instance Object to convert
59
+ # @param [Shale::Mapper] instance Object to convert
60
60
  #
61
61
  # @return [Hash]
62
62
  #
@@ -64,24 +64,26 @@ module Shale
64
64
  def as_#{format}(instance)
65
65
  hash = {}
66
66
 
67
- instance.class.#{format}_mapping.keys.each do |key, attr|
68
- if attr.is_a?(Hash)
69
- hash[key] = instance.send(attr[:to])
67
+ instance.class.#{format}_mapping.keys.each_value do |mapping|
68
+ if mapping.method_to
69
+ hash[mapping.name] = instance.send(mapping.method_to)
70
70
  else
71
- attribute = instance.class.attributes[attr]
71
+ attribute = instance.class.attributes[mapping.attribute]
72
72
  next unless attribute
73
73
 
74
74
  value = instance.public_send(attribute.name)
75
75
 
76
76
  if value.nil?
77
- hash[key] = nil
77
+ hash[mapping.name] = nil
78
78
  next
79
79
  end
80
80
 
81
81
  if attribute.collection?
82
- hash[key] = [*value].map { |v| v ? attribute.type.as_#{format}(v) : v }
82
+ hash[mapping.name] = [*value].map do |v|
83
+ v ? attribute.type.as_#{format}(v) : v
84
+ end
83
85
  else
84
- hash[key] = attribute.type.as_#{format}(value)
86
+ hash[mapping.name] = attribute.type.as_#{format}(value)
85
87
  end
86
88
  end
87
89
  end
@@ -91,7 +93,7 @@ module Shale
91
93
  RUBY
92
94
  end
93
95
 
94
- alias from_hash out_of_hash
96
+ alias from_hash of_hash
95
97
 
96
98
  alias to_hash as_hash
97
99
 
@@ -103,18 +105,19 @@ module Shale
103
105
  #
104
106
  # @api public
105
107
  def from_json(json)
106
- out_of_json(Shale.json_adapter.load(json))
108
+ of_json(Shale.json_adapter.load(json))
107
109
  end
108
110
 
109
111
  # Convert Object to JSON
110
112
  #
111
- # @param [Shale::Type::Base] instance Object to convert
113
+ # @param [Shale::Mapper] instance Object to convert
114
+ # @param [Array<Symbol>] options
112
115
  #
113
116
  # @return [String]
114
117
  #
115
118
  # @api public
116
- def to_json(instance)
117
- Shale.json_adapter.dump(as_json(instance))
119
+ def to_json(instance, *options)
120
+ Shale.json_adapter.dump(as_json(instance), *options)
118
121
  end
119
122
 
120
123
  # Convert YAML to Object
@@ -125,12 +128,12 @@ module Shale
125
128
  #
126
129
  # @api public
127
130
  def from_yaml(yaml)
128
- out_of_yaml(Shale.yaml_adapter.load(yaml))
131
+ of_yaml(Shale.yaml_adapter.load(yaml))
129
132
  end
130
133
 
131
134
  # Convert Object to YAML
132
135
  #
133
- # @param [Shale::Type::Base] instance Object to convert
136
+ # @param [Shale::Mapper] instance Object to convert
134
137
  #
135
138
  # @return [String]
136
139
  #
@@ -146,17 +149,17 @@ module Shale
146
149
  # @return [Shale::Mapper]
147
150
  #
148
151
  # @api public
149
- def out_of_xml(element)
152
+ def of_xml(element)
150
153
  instance = new
151
154
 
152
155
  element.attributes.each do |key, value|
153
156
  mapping = xml_mapping.attributes[key.to_s]
154
157
  next unless mapping
155
158
 
156
- if mapping.is_a?(Hash)
157
- instance.send(mapping[:from], value)
159
+ if mapping.method_from
160
+ instance.send(mapping.method_from, value)
158
161
  else
159
- attribute = attributes[mapping]
162
+ attribute = attributes[mapping.attribute]
160
163
  next unless attribute
161
164
 
162
165
  if attribute.collection?
@@ -171,7 +174,7 @@ module Shale
171
174
  attribute = attributes[xml_mapping.content]
172
175
 
173
176
  if attribute
174
- instance.public_send("#{attribute.name}=", attribute.type.out_of_xml(element))
177
+ instance.public_send("#{attribute.name}=", attribute.type.of_xml(element))
175
178
  end
176
179
  end
177
180
 
@@ -179,17 +182,17 @@ module Shale
179
182
  mapping = xml_mapping.elements[node.name]
180
183
  next unless mapping
181
184
 
182
- if mapping.is_a?(Hash)
183
- instance.send(mapping[:from], node)
185
+ if mapping.method_from
186
+ instance.send(mapping.method_from, node)
184
187
  else
185
- attribute = attributes[mapping]
188
+ attribute = attributes[mapping.attribute]
186
189
  next unless attribute
187
190
 
188
191
  if attribute.collection?
189
- value = attribute.type.out_of_xml(node)
192
+ value = attribute.type.of_xml(node)
190
193
  instance.public_send(attribute.name) << attribute.type.cast(value)
191
194
  else
192
- instance.public_send("#{attribute.name}=", attribute.type.out_of_xml(node))
195
+ instance.public_send("#{attribute.name}=", attribute.type.of_xml(node))
193
196
  end
194
197
  end
195
198
  end
@@ -205,12 +208,12 @@ module Shale
205
208
  #
206
209
  # @api public
207
210
  def from_xml(xml)
208
- out_of_xml(Shale.xml_adapter.load(xml))
211
+ of_xml(Shale.xml_adapter.load(xml))
209
212
  end
210
213
 
211
214
  # Convert Object to XML document
212
215
  #
213
- # @param [Shale::Type::Base] instance Object to convert
216
+ # @param [Shale::Mapper] instance Object to convert
214
217
  # @param [String, nil] node_name XML node name
215
218
  # @param [Shale::Adapter::<xml adapter>::Document, nil] doc Object to convert
216
219
  #
@@ -220,24 +223,25 @@ module Shale
220
223
  def as_xml(instance, node_name = nil, doc = nil)
221
224
  unless doc
222
225
  doc = Shale.xml_adapter.create_document
223
- doc.add_element(doc.doc, as_xml(instance, instance.class.xml_mapping.root, doc))
226
+ doc.add_element(doc.doc, as_xml(instance, xml_mapping.prefixed_root, doc))
224
227
  return doc.doc
225
228
  end
226
229
 
227
230
  element = doc.create_element(node_name)
231
+ doc.add_namespace(xml_mapping.default_namespace.prefix, xml_mapping.default_namespace.name)
228
232
 
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)
233
+ xml_mapping.attributes.each_value do |mapping|
234
+ if mapping.method_to
235
+ instance.send(mapping.method_to, element, doc)
232
236
  else
233
- attribute = instance.class.attributes[obj_attr]
237
+ attribute = instance.class.attributes[mapping.attribute]
234
238
  next unless attribute
235
239
 
236
240
  value = instance.public_send(attribute.name)
241
+ next if value.nil?
237
242
 
238
- if value && !value.empty?
239
- doc.add_attribute(element, xml_attr, value)
240
- end
243
+ doc.add_namespace(mapping.namespace.prefix, mapping.namespace.name)
244
+ doc.add_attribute(element, mapping.prefixed_name, value)
241
245
  end
242
246
  end
243
247
 
@@ -250,23 +254,25 @@ module Shale
250
254
  end
251
255
  end
252
256
 
253
- xml_mapping.elements.each do |xml_name, obj_attr|
254
- if obj_attr.is_a?(Hash)
255
- instance.send(obj_attr[:to], element, doc)
257
+ xml_mapping.elements.each_value do |mapping|
258
+ if mapping.method_to
259
+ instance.send(mapping.method_to, element, doc)
256
260
  else
257
- attribute = instance.class.attributes[obj_attr]
261
+ attribute = instance.class.attributes[mapping.attribute]
258
262
  next unless attribute
259
263
 
260
264
  value = instance.public_send(attribute.name)
261
265
  next if value.nil?
262
266
 
267
+ doc.add_namespace(mapping.namespace.prefix, mapping.namespace.name)
268
+
263
269
  if attribute.collection?
264
270
  [*value].each do |v|
265
271
  next if v.nil?
266
- doc.add_element(element, attribute.type.as_xml(v, xml_name, doc))
272
+ doc.add_element(element, attribute.type.as_xml(v, mapping.prefixed_name, doc))
267
273
  end
268
274
  else
269
- doc.add_element(element, attribute.type.as_xml(value, xml_name, doc))
275
+ doc.add_element(element, attribute.type.as_xml(value, mapping.prefixed_name, doc))
270
276
  end
271
277
  end
272
278
  end
@@ -276,13 +282,14 @@ module Shale
276
282
 
277
283
  # Convert Object to XML
278
284
  #
279
- # @param [Shale::Type::Base] instance Object to convert
285
+ # @param [Shale::Mapper] instance Object to convert
286
+ # @param [Array<Symbol>] options
280
287
  #
281
288
  # @return [String]
282
289
  #
283
290
  # @api public
284
- def to_xml(instance)
285
- Shale.xml_adapter.dump(as_xml(instance))
291
+ def to_xml(instance, *options)
292
+ Shale.xml_adapter.dump(as_xml(instance), *options)
286
293
  end
287
294
  end
288
295
 
@@ -297,11 +304,13 @@ module Shale
297
304
 
298
305
  # Convert Object to JSON
299
306
  #
307
+ # @param [Array<Symbol>] options
308
+ #
300
309
  # @return [String]
301
310
  #
302
311
  # @api public
303
- def to_json
304
- self.class.to_json(self)
312
+ def to_json(*options)
313
+ self.class.to_json(self, *options)
305
314
  end
306
315
 
307
316
  # Convert Object to YAML
@@ -315,11 +324,13 @@ module Shale
315
324
 
316
325
  # Convert Object to XML
317
326
  #
327
+ # @param [Array<Symbol>] options
328
+ #
318
329
  # @return [String]
319
330
  #
320
331
  # @api public
321
- def to_xml
322
- self.class.to_xml(self)
332
+ def to_xml(*options)
333
+ self.class.to_xml(self, *options)
323
334
  end
324
335
  end
325
336
  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.1'
5
+ VERSION = '0.3.1'
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