shale 0.7.1 → 0.9.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 468fc4f3fa1ccd796958748eea653aaa9aec0dbf223c2e5486ddba00350d79fc
4
- data.tar.gz: 4b78746e97bc6fd080b8a6566be2534c3a1c05017acacabd3935f7e2ea81b097
3
+ metadata.gz: 3f880bc8d984c45e7e8a05bd155c1014df237e037263c7bf68a7ae82c0e49ea4
4
+ data.tar.gz: ba7a2f12bed87e048dd53d43900f1c8203d90f5f89a43b3824475ddda39eb07b
5
5
  SHA512:
6
- metadata.gz: 776a30c22e95f8c85e150b64ec7df09e89aeb4e86fb2f6f0fcec67a438b13b73926c3d5419b8194f457a2f09fc8eb64bf491e8b1ea5c5d6957e1e1b5cfab9549
7
- data.tar.gz: 0d236bde4f3b5aaf9b3ea5a5b8380b3861b24f5d0b310430329c68d010c368890dedbd7f6fad8649b71cd443362c8c6272ebb9c7a234998fa546ecb99e728f44
6
+ metadata.gz: 54023d4f621dae53537f73e0ad79d3736d5d52e605c1a7da2c4bdb06588b348feaae9066ce00b6b3aedc9e84ea23a425884eabf987717ffda6d3c22eccc6325f
7
+ data.tar.gz: e82cad292dab557891cad4f210bfb4a97d2096a6d2151a5a8aef020358accb5986e527e32a141a9a2e3a01d594e9a3adb42c0f7e8d17464517731136f63289a2
data/CHANGELOG.md CHANGED
@@ -1,9 +1,26 @@
1
- ## [0.7.1] - [2022-08-12]
1
+ ## [0.9.0] - 2022-10-31
2
+
3
+ ### Added
4
+ - Support for CSV
5
+ - Allow to specify version and add encoding to XML declaration
6
+ - Support for mapping/generating collections
7
+
8
+ ## [0.8.0] - 2022-08-30
9
+
10
+ ### Added
11
+ - Allow to group mappings using `group` block
12
+ - Bring back Ruby 2.6 support
13
+
14
+ ### Changed
15
+ - Use anonymous module for attributes definition.
16
+ It allows to override accessors and `super` works as expected.
17
+
18
+ ## [0.7.1] - 2022-08-12
2
19
 
3
20
  ### Fixed
4
21
  - Fix broken handling of Date and Time types
5
22
 
6
- ## [0.7.0] - [2022-08-09]
23
+ ## [0.7.0] - 2022-08-09
7
24
 
8
25
  ### Added
9
26
  - `only: []` and `except: []` options that allow to controll what attributes are rendered/parsed
data/README.md CHANGED
@@ -1,23 +1,23 @@
1
1
  # Shale
2
2
 
3
- Shale is a Ruby object mapper and serializer for JSON, YAML, TOML and XML.
4
- It allows you to parse JSON, YAML, TOML and XML data and convert it into Ruby data structures,
5
- as well as serialize data structures into JSON, YAML, TOML or XML.
3
+ Shale is a Ruby object mapper and serializer for JSON, YAML, TOML, CSV and XML.
4
+ It allows you to parse JSON, YAML, TOML, CSV and XML data and convert it into Ruby data structures,
5
+ as well as serialize data structures into JSON, YAML, TOML, CSV or XML.
6
6
 
7
7
  Documentation with interactive examples is available at [Shale website](https://www.shalerb.org)
8
8
 
9
9
  ## Features
10
10
 
11
- * Convert JSON, YAML, TOML and XML to Ruby data model
12
- * Convert Ruby data model to JSON, YAML, TOML and XML
11
+ * Convert JSON, YAML, TOML, CSV and XML to Ruby data model
12
+ * Convert Ruby data model to JSON, YAML, TOML, CSV and XML
13
13
  * Generate JSON and XML Schema from Ruby models
14
14
  * Compile JSON and XML Schema into Ruby models
15
- * Out of the box support for JSON, YAML, Tomlib, toml-rb, Nokogiri, REXML and Ox parsers
15
+ * Out of the box support for JSON, YAML, Tomlib, toml-rb, CSV, Nokogiri, REXML and Ox parsers
16
16
  * Support for custom adapters
17
17
 
18
18
  ## Installation
19
19
 
20
- Shale supports Ruby (MRI) 2.7+
20
+ Shale supports Ruby (MRI) 2.6+
21
21
 
22
22
  Add this line to your application's Gemfile:
23
23
 
@@ -51,9 +51,13 @@ $ gem install shale
51
51
  * [Converting object to Hash](#converting-object-to-hash)
52
52
  * [Converting XML to object](#converting-xml-to-object)
53
53
  * [Converting object to XML](#converting-object-to-xml)
54
+ * [Converting CSV to object](#converting-csv-to-object)
55
+ * [Converting object to CSV](#converting-object-to-csv)
56
+ * [Converting collections](#converting-collections)
54
57
  * [Mapping JSON keys to object attributes](#mapping-json-keys-to-object-attributes)
55
58
  * [Mapping YAML keys to object attributes](#mapping-yaml-keys-to-object-attributes)
56
59
  * [Mapping TOML keys to object attributes](#mapping-toml-keys-to-object-attributes)
60
+ * [Mapping CSV columns to object attributes](#mapping-csv-columns-to-object-attributes)
57
61
  * [Mapping Hash keys to object attributes](#mapping-hash-keys-to-object-attributes)
58
62
  * [Mapping XML elements and attributes to object attributes](#mapping-xml-elements-and-attributes-to-object-attributes)
59
63
  * [Using XML namespaces](#using-xml-namespaces)
@@ -346,6 +350,70 @@ person.to_xml
346
350
  # </person>
347
351
  ```
348
352
 
353
+ ### Converting CSV to object
354
+
355
+ CSV represents a flat data structure, so you can't map properties to complex types directly,
356
+ but you can use methods to map properties to complex types
357
+ (see [Using methods to extract and generate data](#using-methods-to-extract-and-generate-data)
358
+ section).
359
+
360
+ `.from_csv` method allways returns an array of records.
361
+
362
+ ```ruby
363
+ people = Person.from_csv(<<~DATA)
364
+ John,Doe,50,false
365
+ DATA
366
+ ```
367
+
368
+ ### Converting object to CSV
369
+
370
+ ```ruby
371
+ people[0].to_csv # or Person.to_csv(people) if you want to convert a collection
372
+
373
+ # =>
374
+ #
375
+ # John,Doe,50,false
376
+ ```
377
+
378
+ ### Converting collections
379
+
380
+ Shale allows converting collections for formats that support it (JSON, YAML and CSV).
381
+ To convert Ruby array to JSON:
382
+
383
+ ```ruby
384
+ person1 = Person.new(name: 'John Doe')
385
+ person2 = Person.new(name: 'Joe Sixpack')
386
+
387
+ Person.to_json([person1, person2], pretty: true)
388
+ # or Person.to_yaml([person1, person2])
389
+ # or Person.to_csv([person1, person2])
390
+
391
+ # =>
392
+ #
393
+ # [
394
+ # { "name": "John Doe" },
395
+ # { "name": "Joe Sixpack" }
396
+ # ]
397
+ ```
398
+
399
+ To convert JSON array to Ruby:
400
+
401
+ ```ruby
402
+ Person.from_json(<<~JSON)
403
+ [
404
+ { "name": "John Doe" },
405
+ { "name": "Joe Sixpack" }
406
+ ]
407
+ JSON
408
+
409
+ # =>
410
+ #
411
+ # [
412
+ # #<Person:0x00000001033dbce8 @name="John Doe">,
413
+ # #<Person:0x00000001033db4c8 @name="Joe Sixpack">
414
+ # ]
415
+ ```
416
+
349
417
  ### Mapping JSON keys to object attributes
350
418
 
351
419
  By default keys are named the same as attributes. To use custom keys use:
@@ -392,6 +460,24 @@ class Person < Shale::Mapper
392
460
  end
393
461
  ```
394
462
 
463
+ ### Mapping CSV columns to object attributes
464
+
465
+ For CSV the order of mapping matters, the first argument in the `map` method is only
466
+ used as a label in header row. So, in the example below the first column will be mapped
467
+ to `:first_name` attribute and the second column to `:last_name`.
468
+
469
+ ```ruby
470
+ class Person < Shale::Mapper
471
+ attribute :first_name, Shale::Type::String
472
+ attribute :last_name, Shale::Type::String
473
+
474
+ csv do
475
+ map 'firstName', to: :first_name
476
+ map 'lastName', to: :last_name
477
+ end
478
+ end
479
+ ```
480
+
395
481
  ### Mapping Hash keys to object attributes
396
482
 
397
483
  ```ruby
@@ -561,8 +647,9 @@ DATA
561
647
 
562
648
  ### Rendering nil values
563
649
 
564
- By default elements with `nil` value are not rendered. You can change this behavior
565
- by using `render_nil: true` on a mapping.
650
+ For JSON, YAML, TOML and XML by default, elements with `nil` value are not rendered.
651
+ You can change this behavior by using `render_nil: true` on a mapping.
652
+ For CSV the default is to render `nil` elements.
566
653
 
567
654
  ```ruby
568
655
  class Person < Shale::Mapper
@@ -729,6 +816,55 @@ end
729
816
  Person.new(password: 'secret').to_json(context: current_user)
730
817
  ```
731
818
 
819
+ If you want to work on multiple elements at a time you can group them using `group` block:
820
+
821
+ ```ruby
822
+ class Person < Shale::Mapper
823
+ attribute :name, Shale::Type::String
824
+
825
+ json do
826
+ group from: :name_from_json, to: :name_to_json do
827
+ map 'first_name'
828
+ map 'last_name'
829
+ end
830
+ end
831
+
832
+ xml do
833
+ group from: :name_from_xml, to: :name_to_xml do
834
+ map_content
835
+ map_element 'first_name'
836
+ map_attribute 'last_name'
837
+ end
838
+ end
839
+
840
+ def name_from_json(model, value)
841
+ model.name = "#{value['first_name']} #{value['last_name']}"
842
+ end
843
+
844
+ def name_to_json(model, doc)
845
+ doc['first_name'] = model.name.split(' ')[0]
846
+ doc['last_name'] = model.name.split(' ')[1]
847
+ end
848
+
849
+ def name_from_xml(model, value)
850
+ # value => { content: ..., attributes: {}, elements: {} }
851
+ end
852
+
853
+ def name_to_xml(model, element, doc)
854
+ # ...
855
+ end
856
+ end
857
+
858
+ Person.from_json(<<~DATA)
859
+ {
860
+ "first_name": "John",
861
+ "last_name": "Doe"
862
+ }
863
+ DATA
864
+
865
+ # => #<Person:0x00007f9bc3086d60 @name="John Doe">
866
+ ```
867
+
732
868
  ### Additional options
733
869
 
734
870
  You can control which attributes to render and parse by
@@ -804,19 +940,52 @@ person.to_json(pretty: true)
804
940
  # }
805
941
  ```
806
942
 
807
- You can also add an XML declaration by passing `declaration: true` to `#to_xml`
943
+ You can also add an XML declaration by passing `declaration: true` and `encoding: true`
944
+ or if you want to spcify version: `declaration: '1.1'` and `encoding: 'ASCII'` to `#to_xml`
808
945
 
809
946
  ```ruby
810
- person.to_xml(pretty: true, declaration: true)
947
+ person.to_xml(pretty: true, declaration: true, encoding: true)
811
948
 
812
949
  # =>
813
950
  #
814
- # <?xml version="1.0"?>
951
+ # <?xml version="1.0" encoding="UTF-8"?>
815
952
  # <Person>
816
953
  # <Address city="London"/>
817
954
  # </Person>
818
955
  ```
819
956
 
957
+ For CSV you can pass `headers: true` to indicate that the first row contains column
958
+ names and shouldn't be included in the returned collection. It also accepts all the options that
959
+ [CSV parser](https://ruby-doc.org/stdlib-3.1.2/libdoc/csv/rdoc/CSV.html#class-CSV-label-Options) accepts.
960
+
961
+ ```ruby
962
+ class Person
963
+ attribute :first_name, Shale::Type::String
964
+ attribute :last_name, Shale::Type::String
965
+ end
966
+
967
+ people = Person.from_csv(<<~DATA, headers: true, col_sep: '|')
968
+ first_name|last_name
969
+ John|Doe
970
+ James|Sixpack
971
+ DATA
972
+
973
+ # =>
974
+ #
975
+ # [
976
+ # #<Person:0x0000000113d7a488 @first_name="John", @last_name="Doe">,
977
+ # #<Person:0x0000000113d7a488 @first_name="James", @last_name="Sixpack">
978
+ # ]
979
+
980
+ Person.to_csv(people, headers: true, col_sep: '|')
981
+
982
+ # =>
983
+ #
984
+ # first_name|last_name
985
+ # John|Doe
986
+ # James|Sixpack
987
+ ```
988
+
820
989
  ### Using custom models
821
990
 
822
991
  By default Shale combines mapper and model into one class. If you want to use your own classes
@@ -906,10 +1075,10 @@ end
906
1075
  ### Adapters
907
1076
 
908
1077
  Shale uses adapters for parsing and generating documents.
909
- By default Ruby's standard JSON, YAML parsers are used for handling JSON and YAML documents.
1078
+ By default Ruby's standard JSON, YAML, CSV parsers are used for handling JSON YAML, CSV documents.
910
1079
 
911
- You can change it by providing your own adapter. For JSON, YAML and TOML, adapter must implement
912
- `.load` and `.dump` class methods.
1080
+ You can change it by providing your own adapter. For JSON, YAML, TOML and CSV adapter must
1081
+ implement `.load` and `.dump` class methods.
913
1082
 
914
1083
  ```ruby
915
1084
  require 'shale'
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'csv'
4
+
5
+ module Shale
6
+ module Adapter
7
+ # CSV adapter
8
+ #
9
+ # @api public
10
+ class CSV
11
+ # Parse CSV into Array<Hash<String, any>>
12
+ #
13
+ # @param [String] csv CSV document
14
+ # @param [Array<String>] headers
15
+ # @param [Hash] options
16
+ #
17
+ # @return [Array<Hash<String, any>>]
18
+ #
19
+ # @api private
20
+ def self.load(csv, headers:, **options)
21
+ ::CSV.parse(csv, headers: headers, **options).map(&:to_h)
22
+ end
23
+
24
+ # Serialize Array<Hash<String, any>> into CSV
25
+ #
26
+ # @param [Array<Hash<String, any>>] obj Array<Hash<String, any>> object
27
+ # @param [Array<String>] headers
28
+ # @param [Hash] options
29
+ #
30
+ # @return [String]
31
+ #
32
+ # @api private
33
+ def self.dump(obj, headers:, **options)
34
+ ::CSV.generate(**options) do |csv|
35
+ obj.each do |row|
36
+ values = []
37
+
38
+ headers.each do |header|
39
+ values << row[header] if row.key?(header)
40
+ end
41
+
42
+ csv << values
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -9,9 +9,14 @@ module Shale
9
9
  class Document
10
10
  # Initialize object
11
11
  #
12
+ # @param [String, nil] version
13
+ #
12
14
  # @api private
13
- def initialize
14
- @doc = ::Nokogiri::XML::Document.new
15
+ def initialize(version = nil)
16
+ ver = nil
17
+ ver = version if version.is_a?(String)
18
+
19
+ @doc = ::Nokogiri::XML::Document.new(ver)
15
20
  @namespaces = {}
16
21
  end
17
22
 
@@ -37,12 +37,13 @@ module Shale
37
37
  #
38
38
  # @param [::Nokogiri::XML::Document] doc Nokogiri document
39
39
  # @param [true, false] pretty
40
- # @param [true, false] declaration
40
+ # @param [true, false, String] declaration
41
+ # @param [true, false, String] encoding
41
42
  #
42
43
  # @return [String]
43
44
  #
44
45
  # @api private
45
- def self.dump(doc, pretty: false, declaration: false)
46
+ def self.dump(doc, pretty: false, declaration: false, encoding: false)
46
47
  save_with = ::Nokogiri::XML::Node::SaveOptions::AS_XML
47
48
 
48
49
  if pretty
@@ -53,6 +54,10 @@ module Shale
53
54
  save_with |= ::Nokogiri::XML::Node::SaveOptions::NO_DECLARATION
54
55
  end
55
56
 
57
+ if encoding
58
+ doc.encoding = encoding == true ? 'UTF-8' : encoding
59
+ end
60
+
56
61
  result = doc.to_xml(save_with: save_with)
57
62
 
58
63
  unless pretty
@@ -64,9 +69,11 @@ module Shale
64
69
 
65
70
  # Create Shale::Adapter::Nokogiri::Document instance
66
71
  #
72
+ # @param [true, false, String, nil] declaration
73
+ #
67
74
  # @api private
68
- def self.create_document
69
- Document.new
75
+ def self.create_document(version = nil)
76
+ Document.new(version)
70
77
  end
71
78
  end
72
79
  end
@@ -31,12 +31,13 @@ module Shale
31
31
  #
32
32
  # @param [::Ox::Document, ::Ox::Element] doc Ox document
33
33
  # @param [true, false] pretty
34
- # @param [true, false] declaration
34
+ # @param [true, false, String] declaration
35
+ # @param [true, false, String] encoding
35
36
  #
36
37
  # @return [String]
37
38
  #
38
39
  # @api private
39
- def self.dump(doc, pretty: false, declaration: false)
40
+ def self.dump(doc, pretty: false, declaration: false, encoding: false)
40
41
  opts = { indent: -1, with_xml: false }
41
42
 
42
43
  if pretty
@@ -44,7 +45,12 @@ module Shale
44
45
  end
45
46
 
46
47
  if declaration
47
- doc[:version] = '1.0'
48
+ doc[:version] = declaration == true ? '1.0' : declaration
49
+
50
+ if encoding
51
+ doc[:encoding] = encoding == true ? 'UTF-8' : encoding
52
+ end
53
+
48
54
  opts[:with_xml] = true
49
55
  end
50
56
 
@@ -54,7 +60,7 @@ module Shale
54
60
  # Create Shale::Adapter::Ox::Document instance
55
61
  #
56
62
  # @api private
57
- def self.create_document
63
+ def self.create_document(_version = nil)
58
64
  Document.new
59
65
  end
60
66
  end
@@ -32,14 +32,28 @@ module Shale
32
32
  #
33
33
  # @param [::REXML::Document] doc REXML document
34
34
  # @param [true, false] pretty
35
- # @param [true, false] declaration
35
+ # @param [true, false, String] declaration
36
+ # @param [true, false, String] encoding
36
37
  #
37
38
  # @return [String]
38
39
  #
39
40
  # @api private
40
- def self.dump(doc, pretty: false, declaration: false)
41
+ def self.dump(doc, pretty: false, declaration: false, encoding: false)
41
42
  if declaration
42
- doc.add(::REXML::XMLDecl.new)
43
+ ver = nil
44
+ enc = nil
45
+
46
+ if declaration.is_a?(String)
47
+ ver = declaration
48
+ end
49
+
50
+ if encoding == true
51
+ enc = 'UTF-8'
52
+ else
53
+ enc = encoding || nil
54
+ end
55
+
56
+ doc.add(::REXML::XMLDecl.new(ver, enc))
43
57
  end
44
58
 
45
59
  io = StringIO.new
@@ -58,7 +72,7 @@ module Shale
58
72
  # Create Shale::Adapter::REXML::Document instance
59
73
  #
60
74
  # @api private
61
- def self.create_document
75
+ def self.create_document(_version = nil)
62
76
  Document.new
63
77
  end
64
78
  end
data/lib/shale/mapper.rb CHANGED
@@ -49,6 +49,7 @@ module Shale
49
49
  @json_mapping = Mapping::Dict.new
50
50
  @yaml_mapping = Mapping::Dict.new
51
51
  @toml_mapping = Mapping::Dict.new
52
+ @csv_mapping = Mapping::Dict.new(render_nil_default: true)
52
53
  @xml_mapping = Mapping::Xml.new
53
54
 
54
55
  class << self
@@ -87,6 +88,13 @@ module Shale
87
88
  # @api public
88
89
  attr_reader :toml_mapping
89
90
 
91
+ # Return CSV mapping object
92
+ #
93
+ # @return [Shale::Mapping::Dict]
94
+ #
95
+ # @api public
96
+ attr_reader :csv_mapping
97
+
90
98
  # Return XML mapping object
91
99
  #
92
100
  # @return [Shale::Mapping::XML]
@@ -98,6 +106,10 @@ module Shale
98
106
  def inherited(subclass)
99
107
  super
100
108
 
109
+ attributes_module = Module.new
110
+ subclass.instance_variable_set('@attributes_module', attributes_module)
111
+ subclass.include(attributes_module)
112
+
101
113
  subclass.instance_variable_set('@model', subclass)
102
114
  subclass.instance_variable_set('@attributes', @attributes.dup)
103
115
 
@@ -105,12 +117,14 @@ module Shale
105
117
  subclass.instance_variable_set('@__json_mapping_init', @json_mapping.dup)
106
118
  subclass.instance_variable_set('@__yaml_mapping_init', @yaml_mapping.dup)
107
119
  subclass.instance_variable_set('@__toml_mapping_init', @toml_mapping.dup)
120
+ subclass.instance_variable_set('@__csv_mapping_init', @csv_mapping.dup)
108
121
  subclass.instance_variable_set('@__xml_mapping_init', @xml_mapping.dup)
109
122
 
110
123
  subclass.instance_variable_set('@hash_mapping', @hash_mapping.dup)
111
124
  subclass.instance_variable_set('@json_mapping', @json_mapping.dup)
112
125
  subclass.instance_variable_set('@yaml_mapping', @yaml_mapping.dup)
113
126
  subclass.instance_variable_set('@toml_mapping', @toml_mapping.dup)
127
+ subclass.instance_variable_set('@csv_mapping', @csv_mapping.dup)
114
128
 
115
129
  xml_mapping = @xml_mapping.dup
116
130
  xml_mapping.root(Utils.underscore(subclass.name || ''))
@@ -169,9 +183,10 @@ module Shale
169
183
  @json_mapping.map(name.to_s, to: name) unless @json_mapping.finalized?
170
184
  @yaml_mapping.map(name.to_s, to: name) unless @yaml_mapping.finalized?
171
185
  @toml_mapping.map(name.to_s, to: name) unless @toml_mapping.finalized?
186
+ @csv_mapping.map(name.to_s, to: name) unless @csv_mapping.finalized?
172
187
  @xml_mapping.map_element(name.to_s, to: name) unless @xml_mapping.finalized?
173
188
 
174
- class_eval(<<-RUBY, __FILE__, __LINE__ + 1)
189
+ @attributes_module.class_eval(<<-RUBY, __FILE__, __LINE__ + 1)
175
190
  attr_reader :#{name}
176
191
 
177
192
  def #{name}=(val)
@@ -276,6 +291,30 @@ module Shale
276
291
  @toml_mapping.instance_eval(&block)
277
292
  end
278
293
 
294
+ # Define CSV mapping
295
+ #
296
+ # @param [Proc] block
297
+ #
298
+ # @example
299
+ # calss Person < Shale::Mapper
300
+ # attribute :first_name, Shale::Type::String
301
+ # attribute :last_name, Shale::Type::String
302
+ # attribute :age, Shale::Type::Integer
303
+ #
304
+ # csv do
305
+ # map 'first_name', to: :first_name
306
+ # map 'last_name', to: :last_name
307
+ # map 'age', to: :age
308
+ # end
309
+ # end
310
+ #
311
+ # @api public
312
+ def csv(&block)
313
+ @csv_mapping = @__csv_mapping_init.dup
314
+ @csv_mapping.finalize!
315
+ @csv_mapping.instance_eval(&block)
316
+ end
317
+
279
318
  # Define XML mapping
280
319
  #
281
320
  # @param [Proc] block
@@ -35,17 +35,26 @@ module Shale
35
35
  # @api private
36
36
  attr_reader :method_to
37
37
 
38
+ # Return group name
39
+ #
40
+ # @return [String]
41
+ #
42
+ # @api private
43
+ attr_reader :group
44
+
38
45
  # Initialize instance
39
46
  #
40
47
  # @param [String] name
41
48
  # @param [Symbol, nil] attribute
42
49
  # @param [Hash, nil] methods
50
+ # @param [String, nil] group
43
51
  # @param [true, false] render_nil
44
52
  #
45
53
  # @api private
46
- def initialize(name:, attribute:, methods:, render_nil:)
54
+ def initialize(name:, attribute:, methods:, group:, render_nil:)
47
55
  @name = name
48
56
  @attribute = attribute
57
+ @group = group
49
58
  @render_nil = render_nil
50
59
 
51
60
  if methods
@@ -28,13 +28,21 @@ module Shale
28
28
  # @param [String] name
29
29
  # @param [Symbol, String] attribute
30
30
  # @param [Hash, nil] methods
31
+ # @param [String, nil] group
31
32
  # @param [Shale::Mapping::XmlNamespace] namespace
32
33
  # @param [true, false] cdata
33
34
  # @param [true, false] render_nil
34
35
  #
35
36
  # @api private
36
- def initialize(name:, attribute:, methods:, namespace:, cdata:, render_nil:)
37
- super(name: name, attribute: attribute, methods: methods, render_nil: render_nil)
37
+ def initialize(name:, attribute:, methods:, group:, namespace:, cdata:, render_nil:)
38
+ super(
39
+ name: name,
40
+ attribute: attribute,
41
+ methods: methods,
42
+ group: group,
43
+ render_nil: render_nil
44
+ )
45
+
38
46
  @namespace = namespace
39
47
  @cdata = cdata
40
48
  end
@@ -47,6 +55,15 @@ module Shale
47
55
  def prefixed_name
48
56
  [namespace.prefix, name].compact.join(':')
49
57
  end
58
+
59
+ # Return name with XML namespace
60
+ #
61
+ # @return [String]
62
+ #
63
+ # @api private
64
+ def namespaced_name
65
+ [namespace.name, name].compact.join(':')
66
+ end
50
67
  end
51
68
  end
52
69
  end