shale 0.6.0 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +27 -0
- data/LICENSE.txt +1 -1
- data/README.md +222 -30
- data/lib/shale/adapter/json.rb +3 -3
- data/lib/shale/adapter/nokogiri.rb +6 -5
- data/lib/shale/adapter/ox.rb +5 -4
- data/lib/shale/adapter/rexml/document.rb +1 -1
- data/lib/shale/adapter/rexml.rb +5 -4
- data/lib/shale/error.rb +8 -3
- data/lib/shale/mapper.rb +5 -1
- data/lib/shale/mapping/descriptor/dict.rb +21 -1
- data/lib/shale/mapping/descriptor/xml.rb +20 -2
- data/lib/shale/mapping/dict.rb +14 -40
- data/lib/shale/mapping/dict_base.rb +73 -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 +53 -154
- data/lib/shale/mapping/xml_base.rb +227 -0
- data/lib/shale/mapping/xml_group.rb +70 -0
- data/lib/shale/schema/json_generator.rb +1 -3
- data/lib/shale/schema/xml_generator/import.rb +2 -2
- data/lib/shale/schema/xml_generator.rb +4 -6
- data/lib/shale/type/complex.rb +469 -84
- data/lib/shale/type/date.rb +2 -2
- data/lib/shale/type/time.rb +2 -2
- data/lib/shale/type/value.rb +10 -10
- data/lib/shale/version.rb +1 -1
- data/shale.gemspec +1 -1
- metadata +11 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 76c0022b3d2d42be143362c84c6697628781acdce7694fb9bc0f305d3f854964
|
4
|
+
data.tar.gz: 0b0b1b060eab81ebfae80afa3c31c809280b66ebd77e413c5908c4bbd09a081a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 43bc9188d1f07c5c367a8ed94e2a3da6b878a7b7b86773d7898697abbd3937d4de6ae0471f9362c72e8a6be2cc5e5100a5206b2f2cc7155ff2ff8784953ef702
|
7
|
+
data.tar.gz: 0e610703cc73809a78007785962d9a322e515b88ab143a55adfeaa1a0da5961f14d8768a3dec4ad797070bbab165c238123702cbc671f522f86e2934968ff78b
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,30 @@
|
|
1
|
+
## [0.8.0] - 2022-08-30
|
2
|
+
|
3
|
+
### Added
|
4
|
+
- Allow to group mappings using `group` block
|
5
|
+
- Bring back Ruby 2.6 support
|
6
|
+
|
7
|
+
### Changed
|
8
|
+
- Use anonymous module for attributes definition.
|
9
|
+
It allows to override accessors and `super` works as expected.
|
10
|
+
|
11
|
+
## [0.7.1] - 2022-08-12
|
12
|
+
|
13
|
+
### Fixed
|
14
|
+
- Fix broken handling of Date and Time types
|
15
|
+
|
16
|
+
## [0.7.0] - 2022-08-09
|
17
|
+
|
18
|
+
### Added
|
19
|
+
- `only: []` and `except: []` options that allow to controll what attributes are rendered/parsed
|
20
|
+
- `render_nil: true` option that allows to render nil values
|
21
|
+
- Allow to pass a context object to extractor/generator methods
|
22
|
+
|
23
|
+
### Changed
|
24
|
+
- Pass whole document to methods for JSON/YAML/TOML so its behavior is consistent with XML mapping
|
25
|
+
- Convert splat arguments to keyword arguments
|
26
|
+
- RSpec: enable random spec execution and warnings
|
27
|
+
|
1
28
|
## [0.6.0] - 2022-07-05
|
2
29
|
|
3
30
|
### Added
|
data/LICENSE.txt
CHANGED
data/README.md
CHANGED
@@ -12,12 +12,12 @@ Documentation with interactive examples is available at [Shale website](https://
|
|
12
12
|
* Convert Ruby data model to JSON, YAML, TOML 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, toml-rb, Nokogiri, REXML and Ox parsers
|
15
|
+
* Out of the box support for JSON, YAML, Tomlib, toml-rb, Nokogiri, REXML and Ox parsers
|
16
16
|
* Support for custom adapters
|
17
17
|
|
18
18
|
## Installation
|
19
19
|
|
20
|
-
Shale supports Ruby (MRI) 2.
|
20
|
+
Shale supports Ruby (MRI) 2.6+
|
21
21
|
|
22
22
|
Add this line to your application's Gemfile:
|
23
23
|
|
@@ -57,8 +57,9 @@ $ gem install shale
|
|
57
57
|
* [Mapping Hash keys to object attributes](#mapping-hash-keys-to-object-attributes)
|
58
58
|
* [Mapping XML elements and attributes to object attributes](#mapping-xml-elements-and-attributes-to-object-attributes)
|
59
59
|
* [Using XML namespaces](#using-xml-namespaces)
|
60
|
+
* [Rendering nil values](#rendering-nil-values)
|
60
61
|
* [Using methods to extract and generate data](#using-methods-to-extract-and-generate-data)
|
61
|
-
* [
|
62
|
+
* [Additional options](#additional-options)
|
62
63
|
* [Using custom models](#using-custom-models)
|
63
64
|
* [Supported types](#supported-types)
|
64
65
|
* [Writing your own type](#writing-your-own-type)
|
@@ -202,18 +203,23 @@ person.to_yaml
|
|
202
203
|
### Converting TOML to object
|
203
204
|
|
204
205
|
To use TOML with Shale you have to set adapter you want to use.
|
205
|
-
|
206
|
+
Out of the box Shale suports [Tomlib](https://github.com/kgiszczak/tomlib).
|
207
|
+
It also comes with adapter for [toml-rb](https://github.com/emancu/toml-rb) if you prefer that.
|
206
208
|
For details see [Adapters](#adapters) section.
|
207
209
|
|
208
|
-
To set it, first make sure
|
210
|
+
To set it, first make sure Tomlib gem is installed:
|
209
211
|
|
210
212
|
```
|
211
|
-
$ gem install
|
213
|
+
$ gem install tomlib
|
212
214
|
```
|
213
215
|
|
214
216
|
then setup adapter:
|
215
217
|
|
216
218
|
```ruby
|
219
|
+
require 'tomlib'
|
220
|
+
Shale.toml_adapter = Tomlib
|
221
|
+
|
222
|
+
# Alternatively if you'd like to use toml-rb, use:
|
217
223
|
require 'shale/adapter/toml_rb'
|
218
224
|
Shale.toml_adapter = Shale::Adapter::TomlRB
|
219
225
|
```
|
@@ -241,18 +247,16 @@ person.to_toml
|
|
241
247
|
|
242
248
|
# =>
|
243
249
|
#
|
244
|
-
#
|
245
|
-
#
|
246
|
-
#
|
247
|
-
#
|
248
|
-
#
|
249
|
-
#
|
250
|
-
#
|
251
|
-
#
|
252
|
-
#
|
253
|
-
#
|
254
|
-
# street: Oxford Street
|
255
|
-
# zip: E1 6AN
|
250
|
+
# first_name = "John"
|
251
|
+
# last_name = "Doe"
|
252
|
+
# age = 50
|
253
|
+
# married = false
|
254
|
+
# hobbies = [ "Singing", "Dancing" ]
|
255
|
+
#
|
256
|
+
# [address]
|
257
|
+
# city = "London"
|
258
|
+
# street = "Oxford Street"
|
259
|
+
# zip = "E1 6AN"
|
256
260
|
```
|
257
261
|
|
258
262
|
### Converting Hash to object
|
@@ -555,6 +559,52 @@ person = Person.from_xml(<<~DATA)
|
|
555
559
|
DATA
|
556
560
|
```
|
557
561
|
|
562
|
+
### Rendering nil values
|
563
|
+
|
564
|
+
By default elements with `nil` value are not rendered. You can change this behavior
|
565
|
+
by using `render_nil: true` on a mapping.
|
566
|
+
|
567
|
+
```ruby
|
568
|
+
class Person < Shale::Mapper
|
569
|
+
attribute :first_name, Shale::Type::String
|
570
|
+
attribute :last_name, Shale::Type::String
|
571
|
+
attribute :age, Shale::Type::Integer
|
572
|
+
|
573
|
+
json do
|
574
|
+
map 'first_name', to: :first_name, render_nil: true
|
575
|
+
map 'last_name', to: :last_name, render_nil: false
|
576
|
+
map 'age', to: :age, render_nil: true
|
577
|
+
end
|
578
|
+
|
579
|
+
xml do
|
580
|
+
root 'person'
|
581
|
+
|
582
|
+
map_element 'first_name', to: :first_name, render_nil: true
|
583
|
+
map_element 'last_name', to: :last_name, render_nil: false
|
584
|
+
map_attribute 'age', to: :age, render_nil: true
|
585
|
+
end
|
586
|
+
end
|
587
|
+
|
588
|
+
person = Person.new(first_name: nil, last_name: nil, age: nil)
|
589
|
+
|
590
|
+
puts person.to_json(pretty: true)
|
591
|
+
|
592
|
+
# =>
|
593
|
+
#
|
594
|
+
# {
|
595
|
+
# "first_name": null,
|
596
|
+
# "age": "null"
|
597
|
+
# }
|
598
|
+
|
599
|
+
puts person.to_xml(pretty: true)
|
600
|
+
|
601
|
+
# =>
|
602
|
+
#
|
603
|
+
# <person age="">
|
604
|
+
# <first_name/>
|
605
|
+
# </person>
|
606
|
+
```
|
607
|
+
|
558
608
|
### Using methods to extract and generate data
|
559
609
|
|
560
610
|
If you need full controll over extracting and generating data from/to document,
|
@@ -582,8 +632,8 @@ class Person < Shale::Mapper
|
|
582
632
|
model.hobbies = value.split(',').map(&:strip)
|
583
633
|
end
|
584
634
|
|
585
|
-
def hobbies_to_json(model)
|
586
|
-
model.hobbies.join(', ')
|
635
|
+
def hobbies_to_json(model, doc)
|
636
|
+
doc['hobbies'] = model.hobbies.join(', ')
|
587
637
|
end
|
588
638
|
|
589
639
|
def address_from_json(model, value)
|
@@ -591,8 +641,8 @@ class Person < Shale::Mapper
|
|
591
641
|
model.city = value['city']
|
592
642
|
end
|
593
643
|
|
594
|
-
def address_to_json(model)
|
595
|
-
{ 'street' => model.street, 'city' => model.city }
|
644
|
+
def address_to_json(model, doc)
|
645
|
+
doc['address'] = { 'street' => model.street, 'city' => model.city }
|
596
646
|
end
|
597
647
|
|
598
648
|
def hobbies_from_xml(model, value)
|
@@ -649,12 +699,149 @@ DATA
|
|
649
699
|
# @city="London">
|
650
700
|
```
|
651
701
|
|
652
|
-
|
702
|
+
You can also pass a `context` object that will be available in extractor/generator methods:
|
653
703
|
|
654
|
-
|
704
|
+
```ruby
|
705
|
+
class Person < Shale::Mapper
|
706
|
+
attribute :password, Shale::Type::String
|
707
|
+
|
708
|
+
json do
|
709
|
+
map 'password', using: { from: :password_from_json, to: :password_to_json }
|
710
|
+
end
|
711
|
+
|
712
|
+
def password_from_json(model, value, context)
|
713
|
+
if context.admin?
|
714
|
+
model.password = value
|
715
|
+
else
|
716
|
+
model.password = '*****'
|
717
|
+
end
|
718
|
+
end
|
719
|
+
|
720
|
+
def password_to_json(model, doc, context)
|
721
|
+
if context.admin?
|
722
|
+
doc['password'] = model.password
|
723
|
+
else
|
724
|
+
doc['password'] = '*****'
|
725
|
+
end
|
726
|
+
end
|
727
|
+
end
|
728
|
+
|
729
|
+
Person.new(password: 'secret').to_json(context: current_user)
|
730
|
+
```
|
731
|
+
|
732
|
+
If you want to work on multiple elements at a time you can group them using `group` block:
|
655
733
|
|
656
734
|
```ruby
|
657
|
-
|
735
|
+
class Person < Shale::Mapper
|
736
|
+
attribute :name, Shale::Type::String
|
737
|
+
|
738
|
+
json do
|
739
|
+
group from: :name_from_json, to: :name_to_json do
|
740
|
+
map 'first_name'
|
741
|
+
map 'last_name'
|
742
|
+
end
|
743
|
+
end
|
744
|
+
|
745
|
+
xml do
|
746
|
+
group from: :name_from_xml, to: :name_to_xml do
|
747
|
+
map_content
|
748
|
+
map_element 'first_name'
|
749
|
+
map_attribute 'last_name'
|
750
|
+
end
|
751
|
+
end
|
752
|
+
|
753
|
+
def name_from_json(model, value)
|
754
|
+
model.name = "#{value['first_name']} #{value['last_name']}"
|
755
|
+
end
|
756
|
+
|
757
|
+
def name_to_json(model, doc)
|
758
|
+
doc['first_name'] = model.name.split(' ')[0]
|
759
|
+
doc['last_name'] = model.name.split(' ')[1]
|
760
|
+
end
|
761
|
+
|
762
|
+
def name_from_xml(model, value)
|
763
|
+
# value => { content: ..., attributes: {}, elements: {} }
|
764
|
+
end
|
765
|
+
|
766
|
+
def name_to_xml(model, element, doc)
|
767
|
+
# ...
|
768
|
+
end
|
769
|
+
end
|
770
|
+
|
771
|
+
Person.from_json(<<~DATA)
|
772
|
+
{
|
773
|
+
"first_name": "John",
|
774
|
+
"last_name": "Doe"
|
775
|
+
}
|
776
|
+
DATA
|
777
|
+
|
778
|
+
# => #<Person:0x00007f9bc3086d60 @name="John Doe">
|
779
|
+
```
|
780
|
+
|
781
|
+
### Additional options
|
782
|
+
|
783
|
+
You can control which attributes to render and parse by
|
784
|
+
using `only: []` and `except: []` parameters.
|
785
|
+
|
786
|
+
```ruby
|
787
|
+
# e.g. if you have this model graph:
|
788
|
+
person = Person.new(
|
789
|
+
first_name: 'John'
|
790
|
+
last_name: 'Doe',
|
791
|
+
address: Address.new(city: 'London', street: 'Oxford Street')
|
792
|
+
)
|
793
|
+
|
794
|
+
# if you want to render only `first_name` and `address.city` do:
|
795
|
+
person.to_json(only: [:first_name, address: [:city]], pretty: true)
|
796
|
+
|
797
|
+
# =>
|
798
|
+
#
|
799
|
+
# {
|
800
|
+
# "first_name": "John",
|
801
|
+
# "address": {
|
802
|
+
# "city": "London"
|
803
|
+
# }
|
804
|
+
# }
|
805
|
+
|
806
|
+
# and if you don't need an address you can do:
|
807
|
+
person.to_json(except: [:address], pretty: true)
|
808
|
+
|
809
|
+
# =>
|
810
|
+
#
|
811
|
+
# {
|
812
|
+
# "first_name": "John",
|
813
|
+
# "last_name": "Doe"
|
814
|
+
# }
|
815
|
+
```
|
816
|
+
|
817
|
+
It works the same for parsing:
|
818
|
+
|
819
|
+
```ruby
|
820
|
+
# e.g. if you want to parse only `address.city` do:
|
821
|
+
Person.from_json(doc, only: [address: [:city]])
|
822
|
+
|
823
|
+
# =>
|
824
|
+
#
|
825
|
+
# #<Person:0x0000000113d7a488
|
826
|
+
# @first_name=nil,
|
827
|
+
# @last_name=nil,
|
828
|
+
# @address=#<Address:0x0000000113d7a140 @street=nil, @city="London">>
|
829
|
+
|
830
|
+
# and if you don't need an `address`:
|
831
|
+
Person.from_json(doc, except: [:address])
|
832
|
+
|
833
|
+
# =>
|
834
|
+
#
|
835
|
+
# #<Person:0x0000000113d7a488
|
836
|
+
# @first_name="John",
|
837
|
+
# @last_name="Doe",
|
838
|
+
# @address=nil>
|
839
|
+
```
|
840
|
+
|
841
|
+
If you need formatted output you can pass `pretty: true` parameter to `#to_json` and `#to_xml`
|
842
|
+
|
843
|
+
```ruby
|
844
|
+
person.to_json(pretty: true)
|
658
845
|
|
659
846
|
# =>
|
660
847
|
#
|
@@ -666,10 +853,10 @@ person.to_json(:pretty)
|
|
666
853
|
# }
|
667
854
|
```
|
668
855
|
|
669
|
-
You can also add an XML declaration by passing
|
856
|
+
You can also add an XML declaration by passing `declaration: true` to `#to_xml`
|
670
857
|
|
671
858
|
```ruby
|
672
|
-
person.to_xml(:
|
859
|
+
person.to_xml(pretty: true, declaration: true)
|
673
860
|
|
674
861
|
# =>
|
675
862
|
#
|
@@ -726,7 +913,7 @@ DATA
|
|
726
913
|
# @last_name="Doe",
|
727
914
|
# @address=#<Address:0x0000000113d7a140 @street="Oxford Street", @city="London">>
|
728
915
|
|
729
|
-
PersonMapper.to_json(person, :
|
916
|
+
PersonMapper.to_json(person, pretty: true)
|
730
917
|
|
731
918
|
# =>
|
732
919
|
#
|
@@ -781,12 +968,17 @@ Shale.json_adapter = MultiJson
|
|
781
968
|
Shale.yaml_adapter = MyYamlAdapter
|
782
969
|
```
|
783
970
|
|
784
|
-
To handle TOML documents you have to set TOML adapter.
|
785
|
-
Shale provides adapter for `toml-rb`
|
971
|
+
To handle TOML documents you have to set TOML adapter. Out of the box `Tomlib` is supported.
|
972
|
+
Shale also provides adapter for `toml-rb` parser:
|
786
973
|
|
787
974
|
```ruby
|
788
975
|
require 'shale'
|
789
976
|
|
977
|
+
# if you want to use Tomlib
|
978
|
+
require 'tomlib'
|
979
|
+
Shale.toml_adapter = Tomlib
|
980
|
+
|
981
|
+
# if you want to use toml-rb
|
790
982
|
require 'shale/adapter/toml_rb'
|
791
983
|
Shale.toml_adapter = Shale::Adapter::TomlRB
|
792
984
|
```
|
data/lib/shale/adapter/json.rb
CHANGED
@@ -22,13 +22,13 @@ module Shale
|
|
22
22
|
# Serialize Hash into JSON
|
23
23
|
#
|
24
24
|
# @param [Hash] obj Hash object
|
25
|
-
# @param [
|
25
|
+
# @param [true, false] pretty
|
26
26
|
#
|
27
27
|
# @return [String]
|
28
28
|
#
|
29
29
|
# @api private
|
30
|
-
def self.dump(obj,
|
31
|
-
if
|
30
|
+
def self.dump(obj, pretty: false)
|
31
|
+
if pretty
|
32
32
|
::JSON.pretty_generate(obj)
|
33
33
|
else
|
34
34
|
::JSON.generate(obj)
|
@@ -36,25 +36,26 @@ module Shale
|
|
36
36
|
# Serialize Nokogiri document into XML
|
37
37
|
#
|
38
38
|
# @param [::Nokogiri::XML::Document] doc Nokogiri document
|
39
|
-
# @param [
|
39
|
+
# @param [true, false] pretty
|
40
|
+
# @param [true, false] declaration
|
40
41
|
#
|
41
42
|
# @return [String]
|
42
43
|
#
|
43
44
|
# @api private
|
44
|
-
def self.dump(doc,
|
45
|
+
def self.dump(doc, pretty: false, declaration: false)
|
45
46
|
save_with = ::Nokogiri::XML::Node::SaveOptions::AS_XML
|
46
47
|
|
47
|
-
if
|
48
|
+
if pretty
|
48
49
|
save_with |= ::Nokogiri::XML::Node::SaveOptions::FORMAT
|
49
50
|
end
|
50
51
|
|
51
|
-
unless
|
52
|
+
unless declaration
|
52
53
|
save_with |= ::Nokogiri::XML::Node::SaveOptions::NO_DECLARATION
|
53
54
|
end
|
54
55
|
|
55
56
|
result = doc.to_xml(save_with: save_with)
|
56
57
|
|
57
|
-
unless
|
58
|
+
unless pretty
|
58
59
|
result = result.sub(/\n/, '')
|
59
60
|
end
|
60
61
|
|
data/lib/shale/adapter/ox.rb
CHANGED
@@ -30,19 +30,20 @@ module Shale
|
|
30
30
|
# Serialize Ox document into XML
|
31
31
|
#
|
32
32
|
# @param [::Ox::Document, ::Ox::Element] doc Ox document
|
33
|
-
# @param [
|
33
|
+
# @param [true, false] pretty
|
34
|
+
# @param [true, false] declaration
|
34
35
|
#
|
35
36
|
# @return [String]
|
36
37
|
#
|
37
38
|
# @api private
|
38
|
-
def self.dump(doc,
|
39
|
+
def self.dump(doc, pretty: false, declaration: false)
|
39
40
|
opts = { indent: -1, with_xml: false }
|
40
41
|
|
41
|
-
if
|
42
|
+
if pretty
|
42
43
|
opts[:indent] = 2
|
43
44
|
end
|
44
45
|
|
45
|
-
if
|
46
|
+
if declaration
|
46
47
|
doc[:version] = '1.0'
|
47
48
|
opts[:with_xml] = true
|
48
49
|
end
|
data/lib/shale/adapter/rexml.rb
CHANGED
@@ -31,19 +31,20 @@ module Shale
|
|
31
31
|
# Serialize REXML document into XML
|
32
32
|
#
|
33
33
|
# @param [::REXML::Document] doc REXML document
|
34
|
-
# @param [
|
34
|
+
# @param [true, false] pretty
|
35
|
+
# @param [true, false] declaration
|
35
36
|
#
|
36
37
|
# @return [String]
|
37
38
|
#
|
38
39
|
# @api private
|
39
|
-
def self.dump(doc,
|
40
|
-
if
|
40
|
+
def self.dump(doc, pretty: false, declaration: false)
|
41
|
+
if declaration
|
41
42
|
doc.add(::REXML::XMLDecl.new)
|
42
43
|
end
|
43
44
|
|
44
45
|
io = StringIO.new
|
45
46
|
|
46
|
-
if
|
47
|
+
if pretty
|
47
48
|
formatter = ::REXML::Formatters::Pretty.new
|
48
49
|
formatter.compact = true
|
49
50
|
else
|
data/lib/shale/error.rb
CHANGED
@@ -7,6 +7,11 @@ module Shale
|
|
7
7
|
TOML Adapter is not set.
|
8
8
|
To use Shale with TOML documents you have to install parser and set adapter.
|
9
9
|
|
10
|
+
# To use Tomlib:
|
11
|
+
# Make sure tomlib is installed eg. execute: gem install tomlib
|
12
|
+
Shale.toml_adapter = Tomlib
|
13
|
+
|
14
|
+
# To use toml-rb:
|
10
15
|
# Make sure toml-rb is installed eg. execute: gem install toml-rb
|
11
16
|
require 'shale/adapter/toml_rb'
|
12
17
|
Shale.toml_adapter = Shale::Adapter::TomlRB
|
@@ -18,16 +23,16 @@ module Shale
|
|
18
23
|
XML Adapter is not set.
|
19
24
|
To use Shale with XML documents you have to install parser and set adapter.
|
20
25
|
|
21
|
-
To use REXML:
|
26
|
+
# To use REXML:
|
22
27
|
require 'shale/adapter/rexml'
|
23
28
|
Shale.xml_adapter = Shale::Adapter::REXML
|
24
29
|
|
25
|
-
To use Nokogiri:
|
30
|
+
# To use Nokogiri:
|
26
31
|
# Make sure Nokogiri is installed eg. execute: gem install nokogiri
|
27
32
|
require 'shale/adapter/nokogiri'
|
28
33
|
Shale.xml_adapter = Shale::Adapter::Nokogiri
|
29
34
|
|
30
|
-
To use OX:
|
35
|
+
# To use OX:
|
31
36
|
# Make sure Ox is installed eg. execute: gem install ox
|
32
37
|
require 'shale/adapter/ox'
|
33
38
|
Shale.xml_adapter = Shale::Adapter::Ox
|
data/lib/shale/mapper.rb
CHANGED
@@ -98,6 +98,10 @@ module Shale
|
|
98
98
|
def inherited(subclass)
|
99
99
|
super
|
100
100
|
|
101
|
+
attributes_module = Module.new
|
102
|
+
subclass.instance_variable_set('@attributes_module', attributes_module)
|
103
|
+
subclass.include(attributes_module)
|
104
|
+
|
101
105
|
subclass.instance_variable_set('@model', subclass)
|
102
106
|
subclass.instance_variable_set('@attributes', @attributes.dup)
|
103
107
|
|
@@ -171,7 +175,7 @@ module Shale
|
|
171
175
|
@toml_mapping.map(name.to_s, to: name) unless @toml_mapping.finalized?
|
172
176
|
@xml_mapping.map_element(name.to_s, to: name) unless @xml_mapping.finalized?
|
173
177
|
|
174
|
-
class_eval(<<-RUBY, __FILE__, __LINE__ + 1)
|
178
|
+
@attributes_module.class_eval(<<-RUBY, __FILE__, __LINE__ + 1)
|
175
179
|
attr_reader :#{name}
|
176
180
|
|
177
181
|
def #{name}=(val)
|
@@ -35,22 +35,42 @@ 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
|
51
|
+
# @param [true, false] render_nil
|
43
52
|
#
|
44
53
|
# @api private
|
45
|
-
def initialize(name:, attribute:, methods:)
|
54
|
+
def initialize(name:, attribute:, methods:, group:, render_nil:)
|
46
55
|
@name = name
|
47
56
|
@attribute = attribute
|
57
|
+
@group = group
|
58
|
+
@render_nil = render_nil
|
48
59
|
|
49
60
|
if methods
|
50
61
|
@method_from = methods[:from]
|
51
62
|
@method_to = methods[:to]
|
52
63
|
end
|
53
64
|
end
|
65
|
+
|
66
|
+
# Check render_nil
|
67
|
+
#
|
68
|
+
# @return [true, false]
|
69
|
+
#
|
70
|
+
# @api private
|
71
|
+
def render_nil?
|
72
|
+
@render_nil == true
|
73
|
+
end
|
54
74
|
end
|
55
75
|
end
|
56
76
|
end
|
@@ -28,12 +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
|
34
|
+
# @param [true, false] render_nil
|
33
35
|
#
|
34
36
|
# @api private
|
35
|
-
def initialize(name:, attribute:, methods:, namespace:, cdata:)
|
36
|
-
super(
|
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
|
+
|
37
46
|
@namespace = namespace
|
38
47
|
@cdata = cdata
|
39
48
|
end
|
@@ -46,6 +55,15 @@ module Shale
|
|
46
55
|
def prefixed_name
|
47
56
|
[namespace.prefix, name].compact.join(':')
|
48
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
|
49
67
|
end
|
50
68
|
end
|
51
69
|
end
|