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 +4 -4
- data/CHANGELOG.md +19 -2
- data/README.md +184 -15
- data/lib/shale/adapter/csv.rb +48 -0
- data/lib/shale/adapter/nokogiri/document.rb +7 -2
- data/lib/shale/adapter/nokogiri.rb +11 -4
- data/lib/shale/adapter/ox.rb +10 -4
- data/lib/shale/adapter/rexml.rb +18 -4
- data/lib/shale/mapper.rb +40 -1
- data/lib/shale/mapping/descriptor/dict.rb +10 -1
- data/lib/shale/mapping/descriptor/xml.rb +19 -2
- data/lib/shale/mapping/dict.rb +14 -46
- data/lib/shale/mapping/dict_base.rb +76 -0
- data/lib/shale/mapping/dict_group.rb +41 -0
- data/lib/shale/mapping/group/dict.rb +55 -0
- data/lib/shale/mapping/group/dict_grouping.rb +41 -0
- data/lib/shale/mapping/group/xml.rb +43 -0
- data/lib/shale/mapping/group/xml_grouping.rb +27 -0
- data/lib/shale/mapping/xml.rb +40 -152
- data/lib/shale/mapping/xml_base.rb +227 -0
- data/lib/shale/mapping/xml_group.rb +70 -0
- data/lib/shale/type/complex.rb +198 -18
- data/lib/shale/type/date.rb +11 -0
- data/lib/shale/type/time.rb +11 -0
- data/lib/shale/type/value.rb +22 -0
- data/lib/shale/version.rb +1 -1
- data/lib/shale.rb +30 -4
- data/shale.gemspec +3 -3
- metadata +14 -5
@@ -0,0 +1,227 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'descriptor/xml'
|
4
|
+
require_relative 'descriptor/xml_namespace'
|
5
|
+
require_relative 'validator'
|
6
|
+
|
7
|
+
module Shale
|
8
|
+
module Mapping
|
9
|
+
# Base class for Mapping XML serialization format
|
10
|
+
#
|
11
|
+
# @api private
|
12
|
+
class XmlBase
|
13
|
+
# Return elements mapping hash
|
14
|
+
#
|
15
|
+
# @return [Hash]
|
16
|
+
#
|
17
|
+
# @api private
|
18
|
+
attr_reader :elements
|
19
|
+
|
20
|
+
# Return attributes mapping hash
|
21
|
+
#
|
22
|
+
# @return [Hash]
|
23
|
+
#
|
24
|
+
# @api private
|
25
|
+
attr_reader :attributes
|
26
|
+
|
27
|
+
# Return content mapping
|
28
|
+
#
|
29
|
+
# @return [Symbol]
|
30
|
+
#
|
31
|
+
# @api private
|
32
|
+
attr_reader :content
|
33
|
+
|
34
|
+
# Return default namespace
|
35
|
+
#
|
36
|
+
# @return [Shale::Mapping::Descriptor::XmlNamespace]
|
37
|
+
#
|
38
|
+
# @api private
|
39
|
+
attr_reader :default_namespace
|
40
|
+
|
41
|
+
# Return unprefixed root
|
42
|
+
#
|
43
|
+
# @return [String]
|
44
|
+
#
|
45
|
+
# @api private
|
46
|
+
def unprefixed_root
|
47
|
+
@root
|
48
|
+
end
|
49
|
+
|
50
|
+
# Return prefixed root
|
51
|
+
#
|
52
|
+
# @return [String]
|
53
|
+
#
|
54
|
+
# @api private
|
55
|
+
def prefixed_root
|
56
|
+
[default_namespace.prefix, @root].compact.join(':')
|
57
|
+
end
|
58
|
+
|
59
|
+
# Initialize instance
|
60
|
+
#
|
61
|
+
# @api private
|
62
|
+
def initialize
|
63
|
+
super
|
64
|
+
@elements = {}
|
65
|
+
@attributes = {}
|
66
|
+
@content = nil
|
67
|
+
@root = ''
|
68
|
+
@default_namespace = Descriptor::XmlNamespace.new
|
69
|
+
@finalized = false
|
70
|
+
end
|
71
|
+
|
72
|
+
# Map element to attribute
|
73
|
+
#
|
74
|
+
# @param [String] element
|
75
|
+
# @param [Symbol, nil] to
|
76
|
+
# @param [Hash, nil] using
|
77
|
+
# @param [String, nil] group
|
78
|
+
# @param [String, nil] namespace
|
79
|
+
# @param [String, nil] prefix
|
80
|
+
# @param [true, false] cdata
|
81
|
+
# @param [true, false] render_nil
|
82
|
+
#
|
83
|
+
# @raise [IncorrectMappingArgumentsError] when arguments are incorrect
|
84
|
+
#
|
85
|
+
# @api private
|
86
|
+
def map_element(
|
87
|
+
element,
|
88
|
+
to: nil,
|
89
|
+
using: nil,
|
90
|
+
group: nil,
|
91
|
+
namespace: :undefined,
|
92
|
+
prefix: :undefined,
|
93
|
+
cdata: false,
|
94
|
+
render_nil: false
|
95
|
+
)
|
96
|
+
Validator.validate_arguments(element, to, using)
|
97
|
+
Validator.validate_namespace(element, namespace, prefix)
|
98
|
+
|
99
|
+
if namespace == :undefined && prefix == :undefined
|
100
|
+
nsp = default_namespace.name
|
101
|
+
pfx = default_namespace.prefix
|
102
|
+
else
|
103
|
+
nsp = namespace
|
104
|
+
pfx = prefix
|
105
|
+
end
|
106
|
+
|
107
|
+
namespaced_element = [nsp, element].compact.join(':')
|
108
|
+
|
109
|
+
@elements[namespaced_element] = Descriptor::Xml.new(
|
110
|
+
name: element,
|
111
|
+
attribute: to,
|
112
|
+
methods: using,
|
113
|
+
group: group,
|
114
|
+
namespace: Descriptor::XmlNamespace.new(nsp, pfx),
|
115
|
+
cdata: cdata,
|
116
|
+
render_nil: render_nil
|
117
|
+
)
|
118
|
+
end
|
119
|
+
|
120
|
+
# Map document's attribute to object's attribute
|
121
|
+
#
|
122
|
+
# @param [String] attribute
|
123
|
+
# @param [Symbol, nil] to
|
124
|
+
# @param [Hash, nil] using
|
125
|
+
# @param [String, nil] namespace
|
126
|
+
# @param [String, nil] prefix
|
127
|
+
# @param [true, false] render_nil
|
128
|
+
#
|
129
|
+
# @raise [IncorrectMappingArgumentsError] when arguments are incorrect
|
130
|
+
#
|
131
|
+
# @api private
|
132
|
+
def map_attribute(
|
133
|
+
attribute,
|
134
|
+
to: nil,
|
135
|
+
using: nil,
|
136
|
+
group: nil,
|
137
|
+
namespace: nil,
|
138
|
+
prefix: nil,
|
139
|
+
render_nil: false
|
140
|
+
)
|
141
|
+
Validator.validate_arguments(attribute, to, using)
|
142
|
+
Validator.validate_namespace(attribute, namespace, prefix)
|
143
|
+
|
144
|
+
namespaced_attribute = [namespace, attribute].compact.join(':')
|
145
|
+
|
146
|
+
@attributes[namespaced_attribute] = Descriptor::Xml.new(
|
147
|
+
name: attribute,
|
148
|
+
attribute: to,
|
149
|
+
methods: using,
|
150
|
+
namespace: Descriptor::XmlNamespace.new(namespace, prefix),
|
151
|
+
cdata: false,
|
152
|
+
group: group,
|
153
|
+
render_nil: render_nil
|
154
|
+
)
|
155
|
+
end
|
156
|
+
|
157
|
+
# Map document's content to object's attribute
|
158
|
+
#
|
159
|
+
# @param [Symbol] to
|
160
|
+
# @param [Hash, nil] using
|
161
|
+
# @param [true, false] cdata
|
162
|
+
#
|
163
|
+
# @api private
|
164
|
+
def map_content(to: nil, using: nil, group: nil, cdata: false)
|
165
|
+
Validator.validate_arguments('content', to, using)
|
166
|
+
|
167
|
+
@content = Descriptor::Xml.new(
|
168
|
+
name: nil,
|
169
|
+
attribute: to,
|
170
|
+
methods: using,
|
171
|
+
namespace: Descriptor::XmlNamespace.new(nil, nil),
|
172
|
+
cdata: cdata,
|
173
|
+
group: group,
|
174
|
+
render_nil: false
|
175
|
+
)
|
176
|
+
end
|
177
|
+
|
178
|
+
# Set the name for root element
|
179
|
+
#
|
180
|
+
# @param [String] value root's name
|
181
|
+
#
|
182
|
+
# @api private
|
183
|
+
def root(value)
|
184
|
+
@root = value
|
185
|
+
end
|
186
|
+
|
187
|
+
# Set default namespace for root element
|
188
|
+
#
|
189
|
+
# @param [String] name
|
190
|
+
# @param [String] prefix
|
191
|
+
#
|
192
|
+
# @api private
|
193
|
+
def namespace(name, prefix)
|
194
|
+
@default_namespace.name = name
|
195
|
+
@default_namespace.prefix = prefix
|
196
|
+
end
|
197
|
+
|
198
|
+
# Set the "finalized" instance variable to true
|
199
|
+
#
|
200
|
+
# @api private
|
201
|
+
def finalize!
|
202
|
+
@finalized = true
|
203
|
+
end
|
204
|
+
|
205
|
+
# Query the "finalized" instance variable
|
206
|
+
#
|
207
|
+
# @return [truem false]
|
208
|
+
#
|
209
|
+
# @api private
|
210
|
+
def finalized?
|
211
|
+
@finalized
|
212
|
+
end
|
213
|
+
|
214
|
+
# @api private
|
215
|
+
def initialize_dup(other)
|
216
|
+
@elements = other.instance_variable_get('@elements').dup
|
217
|
+
@attributes = other.instance_variable_get('@attributes').dup
|
218
|
+
@content = other.instance_variable_get('@content').dup
|
219
|
+
@root = other.instance_variable_get('@root').dup
|
220
|
+
@default_namespace = other.instance_variable_get('@default_namespace').dup
|
221
|
+
@finalized = false
|
222
|
+
|
223
|
+
super
|
224
|
+
end
|
225
|
+
end
|
226
|
+
end
|
227
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'xml_base'
|
4
|
+
|
5
|
+
module Shale
|
6
|
+
module Mapping
|
7
|
+
# Group for XML serialization format
|
8
|
+
#
|
9
|
+
# @api private
|
10
|
+
class XmlGroup < XmlBase
|
11
|
+
# Return name of the group
|
12
|
+
#
|
13
|
+
# @return [String]
|
14
|
+
#
|
15
|
+
# @api private
|
16
|
+
attr_reader :name
|
17
|
+
|
18
|
+
# Initialize instance
|
19
|
+
#
|
20
|
+
# @api private
|
21
|
+
def initialize(from, to)
|
22
|
+
super()
|
23
|
+
@from = from
|
24
|
+
@to = to
|
25
|
+
@name = "group_#{hash}"
|
26
|
+
end
|
27
|
+
|
28
|
+
# Map element to attribute
|
29
|
+
#
|
30
|
+
# @param [String] element
|
31
|
+
# @param [String, nil] namespace
|
32
|
+
# @param [String, nil] prefix
|
33
|
+
#
|
34
|
+
# @api private
|
35
|
+
def map_element(element, namespace: :undefined, prefix: :undefined)
|
36
|
+
super(
|
37
|
+
element,
|
38
|
+
using: { from: @from, to: @to },
|
39
|
+
group: @name,
|
40
|
+
namespace: namespace,
|
41
|
+
prefix: prefix
|
42
|
+
)
|
43
|
+
end
|
44
|
+
|
45
|
+
# Map document's attribute to object's attribute
|
46
|
+
#
|
47
|
+
# @param [String] attribute
|
48
|
+
# @param [String, nil] namespace
|
49
|
+
# @param [String, nil] prefix
|
50
|
+
#
|
51
|
+
# @api private
|
52
|
+
def map_attribute(attribute, namespace: nil, prefix: nil)
|
53
|
+
super(
|
54
|
+
attribute,
|
55
|
+
using: { from: @from, to: @to },
|
56
|
+
group: @name,
|
57
|
+
namespace: namespace,
|
58
|
+
prefix: prefix
|
59
|
+
)
|
60
|
+
end
|
61
|
+
|
62
|
+
# Map document's content to object's attribute
|
63
|
+
#
|
64
|
+
# @api private
|
65
|
+
def map_content
|
66
|
+
super(using: { from: @from, to: @to }, group: @name)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
data/lib/shale/type/complex.rb
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require_relative '../error'
|
4
|
+
require_relative '../mapping/group/dict_grouping'
|
5
|
+
require_relative '../mapping/group/xml_grouping'
|
4
6
|
require_relative 'value'
|
5
7
|
|
6
8
|
module Shale
|
@@ -11,11 +13,11 @@ module Shale
|
|
11
13
|
# @api private
|
12
14
|
class Complex < Value
|
13
15
|
class << self
|
14
|
-
%i[hash json yaml toml].each do |format|
|
16
|
+
%i[hash json yaml toml csv].each do |format|
|
15
17
|
class_eval(<<-RUBY, __FILE__, __LINE__ + 1)
|
16
18
|
# Convert Hash to Object using Hash/JSON/YAML/TOML mapping
|
17
19
|
#
|
18
|
-
# @param [Hash] hash Hash to convert
|
20
|
+
# @param [Hash, Array] hash Hash to convert
|
19
21
|
# @param [Array<Symbol>] only
|
20
22
|
# @param [Array<Symbol>] except
|
21
23
|
# @param [any] context
|
@@ -24,6 +26,18 @@ module Shale
|
|
24
26
|
#
|
25
27
|
# @api public
|
26
28
|
def of_#{format}(hash, only: nil, except: nil, context: nil)
|
29
|
+
#{
|
30
|
+
if format != :toml
|
31
|
+
<<~CODE
|
32
|
+
if hash.is_a?(Array)
|
33
|
+
return hash.map do |item|
|
34
|
+
of_#{format}(item, only: only, except: except, context: context)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
CODE
|
38
|
+
end
|
39
|
+
}
|
40
|
+
|
27
41
|
instance = model.new
|
28
42
|
|
29
43
|
attributes
|
@@ -32,6 +46,7 @@ module Shale
|
|
32
46
|
.each { |attr| instance.send(attr.setter, attr.default.call) }
|
33
47
|
|
34
48
|
mapping_keys = #{format}_mapping.keys
|
49
|
+
grouping = Shale::Mapping::Group::DictGrouping.new
|
35
50
|
|
36
51
|
only = to_partial_render_attributes(only)
|
37
52
|
except = to_partial_render_attributes(except)
|
@@ -40,7 +55,9 @@ module Shale
|
|
40
55
|
mapping = mapping_keys[key]
|
41
56
|
next unless mapping
|
42
57
|
|
43
|
-
if mapping.
|
58
|
+
if mapping.group
|
59
|
+
grouping.add(mapping, value)
|
60
|
+
elsif mapping.method_from
|
44
61
|
mapper = new
|
45
62
|
|
46
63
|
if mapper.method(mapping.method_from).arity == 3
|
@@ -89,12 +106,22 @@ module Shale
|
|
89
106
|
end
|
90
107
|
end
|
91
108
|
|
109
|
+
grouping.each do |group|
|
110
|
+
mapper = new
|
111
|
+
|
112
|
+
if mapper.method(group.method_from).arity == 3
|
113
|
+
mapper.send(group.method_from, instance, group.dict, context)
|
114
|
+
else
|
115
|
+
mapper.send(group.method_from, instance, group.dict)
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
92
119
|
instance
|
93
120
|
end
|
94
121
|
|
95
122
|
# Convert Object to Hash using Hash/JSON/YAML/TOML mapping
|
96
123
|
#
|
97
|
-
# @param [any] instance Object to convert
|
124
|
+
# @param [any, Array<any>] instance Object to convert
|
98
125
|
# @param [Array<Symbol>] only
|
99
126
|
# @param [Array<Symbol>] except
|
100
127
|
# @param [any] context
|
@@ -105,18 +132,33 @@ module Shale
|
|
105
132
|
#
|
106
133
|
# @api public
|
107
134
|
def as_#{format}(instance, only: nil, except: nil, context: nil)
|
135
|
+
#{
|
136
|
+
if format != :toml
|
137
|
+
<<~CODE
|
138
|
+
if instance.is_a?(Array)
|
139
|
+
return instance.map do |item|
|
140
|
+
as_#{format}(item, only: only, except: except, context: context)
|
141
|
+
end
|
142
|
+
end
|
143
|
+
CODE
|
144
|
+
end
|
145
|
+
}
|
146
|
+
|
108
147
|
unless instance.is_a?(model)
|
109
148
|
msg = "argument is a '\#{instance.class}' but should be a '\#{model}'"
|
110
149
|
raise IncorrectModelError, msg
|
111
150
|
end
|
112
151
|
|
113
152
|
hash = {}
|
153
|
+
grouping = Shale::Mapping::Group::DictGrouping.new
|
114
154
|
|
115
155
|
only = to_partial_render_attributes(only)
|
116
156
|
except = to_partial_render_attributes(except)
|
117
157
|
|
118
158
|
#{format}_mapping.keys.each_value do |mapping|
|
119
|
-
if mapping.
|
159
|
+
if mapping.group
|
160
|
+
grouping.add(mapping, nil)
|
161
|
+
elsif mapping.method_to
|
120
162
|
mapper = new
|
121
163
|
|
122
164
|
if mapper.method(mapping.method_to).arity == 3
|
@@ -166,6 +208,16 @@ module Shale
|
|
166
208
|
end
|
167
209
|
end
|
168
210
|
|
211
|
+
grouping.each do |group|
|
212
|
+
mapper = new
|
213
|
+
|
214
|
+
if mapper.method(group.method_to).arity == 3
|
215
|
+
mapper.send(group.method_to, instance, hash, context)
|
216
|
+
else
|
217
|
+
mapper.send(group.method_to, instance, hash)
|
218
|
+
end
|
219
|
+
end
|
220
|
+
|
169
221
|
hash
|
170
222
|
end
|
171
223
|
RUBY
|
@@ -284,6 +336,65 @@ module Shale
|
|
284
336
|
)
|
285
337
|
end
|
286
338
|
|
339
|
+
# Convert CSV to Object
|
340
|
+
#
|
341
|
+
# @param [String] csv CSV to convert
|
342
|
+
# @param [Array<Symbol>] only
|
343
|
+
# @param [Array<Symbol>] except
|
344
|
+
# @param [any] context
|
345
|
+
# @param [true, false] headers
|
346
|
+
# @param [Hash] csv_options
|
347
|
+
#
|
348
|
+
# @return [model instance]
|
349
|
+
#
|
350
|
+
# @api public
|
351
|
+
def from_csv(csv, only: nil, except: nil, context: nil, headers: false, **csv_options)
|
352
|
+
data = Shale.csv_adapter.load(csv, **csv_options.merge(headers: csv_mapping.keys.keys))
|
353
|
+
|
354
|
+
data.shift if headers
|
355
|
+
|
356
|
+
of_csv(
|
357
|
+
data,
|
358
|
+
only: only,
|
359
|
+
except: except,
|
360
|
+
context: context
|
361
|
+
)
|
362
|
+
end
|
363
|
+
|
364
|
+
# Convert Object to CSV
|
365
|
+
#
|
366
|
+
# @param [model instance] instance Object to convert
|
367
|
+
# @param [Array<Symbol>] only
|
368
|
+
# @param [Array<Symbol>] except
|
369
|
+
# @param [any] context
|
370
|
+
# @param [true, false] headers
|
371
|
+
# @param [Hash] csv_options
|
372
|
+
#
|
373
|
+
# @return [String]
|
374
|
+
#
|
375
|
+
# @api public
|
376
|
+
def to_csv(instance, only: nil, except: nil, context: nil, headers: false, **csv_options)
|
377
|
+
data = as_csv([*instance], only: only, except: except, context: context)
|
378
|
+
|
379
|
+
cols = csv_mapping.keys.values
|
380
|
+
|
381
|
+
if only
|
382
|
+
cols = cols.select { |e| only.include?(e.attribute) }
|
383
|
+
end
|
384
|
+
|
385
|
+
if except
|
386
|
+
cols = cols.reject { |e| except.include?(e.attribute) }
|
387
|
+
end
|
388
|
+
|
389
|
+
cols = cols.map(&:name)
|
390
|
+
|
391
|
+
if headers
|
392
|
+
data.prepend(cols.to_h { |e| [e, e] })
|
393
|
+
end
|
394
|
+
|
395
|
+
Shale.csv_adapter.dump(data, **csv_options.merge(headers: cols))
|
396
|
+
end
|
397
|
+
|
287
398
|
# Convert XML document to Object
|
288
399
|
#
|
289
400
|
# @param [Shale::Adapter::<XML adapter>::Node] element
|
@@ -302,6 +413,8 @@ module Shale
|
|
302
413
|
.select { |attr| attr.default }
|
303
414
|
.each { |attr| instance.send(attr.setter, attr.default.call) }
|
304
415
|
|
416
|
+
grouping = Shale::Mapping::Group::XmlGrouping.new
|
417
|
+
|
305
418
|
only = to_partial_render_attributes(only)
|
306
419
|
except = to_partial_render_attributes(except)
|
307
420
|
|
@@ -309,7 +422,9 @@ module Shale
|
|
309
422
|
mapping = xml_mapping.attributes[key.to_s]
|
310
423
|
next unless mapping
|
311
424
|
|
312
|
-
if mapping.
|
425
|
+
if mapping.group
|
426
|
+
grouping.add(mapping, :attribute, value)
|
427
|
+
elsif mapping.method_from
|
313
428
|
mapper = new
|
314
429
|
|
315
430
|
if mapper.method(mapping.method_from).arity == 3
|
@@ -335,7 +450,9 @@ module Shale
|
|
335
450
|
content_mapping = xml_mapping.content
|
336
451
|
|
337
452
|
if content_mapping
|
338
|
-
if content_mapping.
|
453
|
+
if content_mapping.group
|
454
|
+
grouping.add(content_mapping, :content, element)
|
455
|
+
elsif content_mapping.method_from
|
339
456
|
mapper = new
|
340
457
|
|
341
458
|
if mapper.method(content_mapping.method_from).arity == 3
|
@@ -366,7 +483,9 @@ module Shale
|
|
366
483
|
mapping = xml_mapping.elements[node.name]
|
367
484
|
next unless mapping
|
368
485
|
|
369
|
-
if mapping.
|
486
|
+
if mapping.group
|
487
|
+
grouping.add(mapping, :element, node)
|
488
|
+
elsif mapping.method_from
|
370
489
|
mapper = new
|
371
490
|
|
372
491
|
if mapper.method(mapping.method_from).arity == 3
|
@@ -403,6 +522,16 @@ module Shale
|
|
403
522
|
end
|
404
523
|
end
|
405
524
|
|
525
|
+
grouping.each do |group|
|
526
|
+
mapper = new
|
527
|
+
|
528
|
+
if mapper.method(group.method_from).arity == 3
|
529
|
+
mapper.send(group.method_from, instance, group.dict, context)
|
530
|
+
else
|
531
|
+
mapper.send(group.method_from, instance, group.dict)
|
532
|
+
end
|
533
|
+
end
|
534
|
+
|
406
535
|
instance
|
407
536
|
end
|
408
537
|
|
@@ -449,7 +578,8 @@ module Shale
|
|
449
578
|
_cdata = nil,
|
450
579
|
only: nil,
|
451
580
|
except: nil,
|
452
|
-
context: nil
|
581
|
+
context: nil,
|
582
|
+
version: nil
|
453
583
|
)
|
454
584
|
unless instance.is_a?(model)
|
455
585
|
msg = "argument is a '#{instance.class}' but should be a '#{model}'"
|
@@ -457,7 +587,7 @@ module Shale
|
|
457
587
|
end
|
458
588
|
|
459
589
|
unless doc
|
460
|
-
doc = Shale.xml_adapter.create_document
|
590
|
+
doc = Shale.xml_adapter.create_document(version)
|
461
591
|
|
462
592
|
element = as_xml(
|
463
593
|
instance,
|
@@ -479,11 +609,15 @@ module Shale
|
|
479
609
|
xml_mapping.default_namespace.name
|
480
610
|
)
|
481
611
|
|
612
|
+
grouping = Shale::Mapping::Group::XmlGrouping.new
|
613
|
+
|
482
614
|
only = to_partial_render_attributes(only)
|
483
615
|
except = to_partial_render_attributes(except)
|
484
616
|
|
485
617
|
xml_mapping.attributes.each_value do |mapping|
|
486
|
-
if mapping.
|
618
|
+
if mapping.group
|
619
|
+
grouping.add(mapping, :attribute, nil)
|
620
|
+
elsif mapping.method_to
|
487
621
|
mapper = new
|
488
622
|
|
489
623
|
if mapper.method(mapping.method_to).arity == 4
|
@@ -510,7 +644,9 @@ module Shale
|
|
510
644
|
content_mapping = xml_mapping.content
|
511
645
|
|
512
646
|
if content_mapping
|
513
|
-
if content_mapping.
|
647
|
+
if content_mapping.group
|
648
|
+
grouping.add(content_mapping, :content, nil)
|
649
|
+
elsif content_mapping.method_to
|
514
650
|
mapper = new
|
515
651
|
|
516
652
|
if mapper.method(content_mapping.method_to).arity == 4
|
@@ -543,7 +679,9 @@ module Shale
|
|
543
679
|
end
|
544
680
|
|
545
681
|
xml_mapping.elements.each_value do |mapping|
|
546
|
-
if mapping.
|
682
|
+
if mapping.group
|
683
|
+
grouping.add(mapping, :element, nil)
|
684
|
+
elsif mapping.method_to
|
547
685
|
mapper = new
|
548
686
|
|
549
687
|
if mapper.method(mapping.method_to).arity == 4
|
@@ -605,6 +743,16 @@ module Shale
|
|
605
743
|
end
|
606
744
|
end
|
607
745
|
|
746
|
+
grouping.each do |group|
|
747
|
+
mapper = new
|
748
|
+
|
749
|
+
if mapper.method(group.method_to).arity == 4
|
750
|
+
mapper.send(group.method_to, instance, element, doc, context)
|
751
|
+
else
|
752
|
+
mapper.send(group.method_to, instance, element, doc)
|
753
|
+
end
|
754
|
+
end
|
755
|
+
|
608
756
|
element
|
609
757
|
end
|
610
758
|
|
@@ -616,6 +764,7 @@ module Shale
|
|
616
764
|
# @param [any] context
|
617
765
|
# @param [true, false] pretty
|
618
766
|
# @param [true, false] declaration
|
767
|
+
# @param [true, false, String] encoding
|
619
768
|
#
|
620
769
|
# @raise [AdapterError]
|
621
770
|
#
|
@@ -628,13 +777,15 @@ module Shale
|
|
628
777
|
except: nil,
|
629
778
|
context: nil,
|
630
779
|
pretty: false,
|
631
|
-
declaration: false
|
780
|
+
declaration: false,
|
781
|
+
encoding: false
|
632
782
|
)
|
633
783
|
validate_xml_adapter
|
634
784
|
Shale.xml_adapter.dump(
|
635
|
-
as_xml(instance, only: only, except: except, context: context),
|
785
|
+
as_xml(instance, only: only, except: except, context: context, version: declaration),
|
636
786
|
pretty: pretty,
|
637
|
-
declaration: declaration
|
787
|
+
declaration: declaration,
|
788
|
+
encoding: encoding
|
638
789
|
)
|
639
790
|
end
|
640
791
|
|
@@ -737,6 +888,26 @@ module Shale
|
|
737
888
|
self.class.to_toml(self, only: only, except: except, context: context)
|
738
889
|
end
|
739
890
|
|
891
|
+
# Convert Object to CSV
|
892
|
+
#
|
893
|
+
# @param [Array<Symbol>] only
|
894
|
+
# @param [Array<Symbol>] except
|
895
|
+
# @param [any] context
|
896
|
+
#
|
897
|
+
# @return [String]
|
898
|
+
#
|
899
|
+
# @api public
|
900
|
+
def to_csv(only: nil, except: nil, context: nil, headers: false, **csv_options)
|
901
|
+
self.class.to_csv(
|
902
|
+
self,
|
903
|
+
only: only,
|
904
|
+
except: except,
|
905
|
+
context: context,
|
906
|
+
headers: headers,
|
907
|
+
**csv_options
|
908
|
+
)
|
909
|
+
end
|
910
|
+
|
740
911
|
# Convert Object to XML
|
741
912
|
#
|
742
913
|
# @param [Array<Symbol>] only
|
@@ -744,18 +915,27 @@ module Shale
|
|
744
915
|
# @param [any] context
|
745
916
|
# @param [true, false] pretty
|
746
917
|
# @param [true, false] declaration
|
918
|
+
# @param [true, false, String] encoding
|
747
919
|
#
|
748
920
|
# @return [String]
|
749
921
|
#
|
750
922
|
# @api public
|
751
|
-
def to_xml(
|
923
|
+
def to_xml(
|
924
|
+
only: nil,
|
925
|
+
except: nil,
|
926
|
+
context: nil,
|
927
|
+
pretty: false,
|
928
|
+
declaration: false,
|
929
|
+
encoding: false
|
930
|
+
)
|
752
931
|
self.class.to_xml(
|
753
932
|
self,
|
754
933
|
only: only,
|
755
934
|
except: except,
|
756
935
|
context: context,
|
757
936
|
pretty: pretty,
|
758
|
-
declaration: declaration
|
937
|
+
declaration: declaration,
|
938
|
+
encoding: encoding
|
759
939
|
)
|
760
940
|
end
|
761
941
|
end
|