activemodel-serializers-xml 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +9 -0
- data/.travis.yml +15 -0
- data/CONTRIBUTING.md +99 -0
- data/Gemfile +4 -0
- data/MIT-LICENSE +21 -0
- data/README.md +89 -0
- data/Rakefile +8 -0
- data/activemodel-serializers-xml.gemspec +26 -0
- data/lib/active_model-serializers.rb +1 -0
- data/lib/active_model/serializers.rb +28 -0
- data/lib/active_model/serializers/version.rb +5 -0
- data/lib/active_model/serializers/xml.rb +238 -0
- data/lib/active_record/serializers/xml_serializer.rb +194 -0
- metadata +156 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 6bc425067f4464c88dee88509467b43023e6403f
|
4
|
+
data.tar.gz: be43d228780d3b5d1fc36e601a6683843dfde5a9
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 94f24ac26395ceee9a15e4b3587acdbb4f43b5d6485b7721dd4d3f111dbdc3c65dc8ae77faa931fb8383eb224082f9870b6f72c6d0bee40b10ce21eafe5e0066
|
7
|
+
data.tar.gz: 7a8b5bf946628353d49a7c746a94cc689d2eaf747a1e73fd3609e97f47e181feedece4e58bc27c4f67f77013480ffce00c21499ed2e37f0838236ede3cfef104
|
data/.gitignore
ADDED
data/.travis.yml
ADDED
data/CONTRIBUTING.md
ADDED
@@ -0,0 +1,99 @@
|
|
1
|
+
Contributing to ActiveModel::Serializers::Xml
|
2
|
+
=====================
|
3
|
+
|
4
|
+
[![Build Status](https://api.travis-ci.org/rails/activemodel-serializers-xml.svg)](https://travis-ci.org/rails/activemodel-serializers-xml)
|
5
|
+
|
6
|
+
ActiveModel::Serializers::Xml is work of [many contributors](https://github.com/rails/activemodel-serializers-xml/graphs/contributors). You're encouraged to submit [pull requests](https://github.com/rails/activemodel-serializers-xml/pulls), [propose features and discuss issues](https://github.com/rails/activemodel-serializers-xml/issues).
|
7
|
+
|
8
|
+
#### Fork the Project
|
9
|
+
|
10
|
+
Fork the [project on Github](https://github.com/rails/activemodel-serializers-xml) and check out your copy.
|
11
|
+
|
12
|
+
```
|
13
|
+
git clone https://github.com/contributor/activemodel-serializers-xml.git
|
14
|
+
cd activemodel-serializers-xml
|
15
|
+
git remote add upstream https://github.com/rails/activemodel-serializers-xml.git
|
16
|
+
```
|
17
|
+
|
18
|
+
#### Create a Topic Branch
|
19
|
+
|
20
|
+
Make sure your fork is up-to-date and create a topic branch for your feature or bug fix.
|
21
|
+
|
22
|
+
```
|
23
|
+
git checkout master
|
24
|
+
git pull upstream master
|
25
|
+
git checkout -b my-feature-branch
|
26
|
+
```
|
27
|
+
|
28
|
+
#### Bundle Install and Test
|
29
|
+
|
30
|
+
Ensure that you can build the project and run tests.
|
31
|
+
|
32
|
+
```
|
33
|
+
bundle install
|
34
|
+
bundle exec rake test
|
35
|
+
```
|
36
|
+
|
37
|
+
#### Write Tests
|
38
|
+
|
39
|
+
Try to write a test that reproduces the problem you're trying to fix or describes a feature that you want to build. Add to [test](test).
|
40
|
+
|
41
|
+
We definitely appreciate pull requests that highlight or reproduce a problem, even without a fix.
|
42
|
+
|
43
|
+
#### Write Code
|
44
|
+
|
45
|
+
Implement your feature or bug fix.
|
46
|
+
|
47
|
+
Make sure that `bundle exec rake test` completes without errors.
|
48
|
+
|
49
|
+
#### Write Documentation
|
50
|
+
|
51
|
+
Document any external behavior in the [README](README.md).
|
52
|
+
|
53
|
+
#### Commit Changes
|
54
|
+
|
55
|
+
Make sure git knows your name and email address:
|
56
|
+
|
57
|
+
```
|
58
|
+
git config --global user.name "Your Name"
|
59
|
+
git config --global user.email "contributor@example.com"
|
60
|
+
```
|
61
|
+
|
62
|
+
Writing good commit logs is important. A commit log should describe what changed and why.
|
63
|
+
|
64
|
+
```
|
65
|
+
git add ...
|
66
|
+
git commit
|
67
|
+
```
|
68
|
+
|
69
|
+
#### Push
|
70
|
+
|
71
|
+
```
|
72
|
+
git push origin my-feature-branch
|
73
|
+
```
|
74
|
+
|
75
|
+
#### Make a Pull Request
|
76
|
+
|
77
|
+
Go to https://github.com/contributor/activemodel-serializers-xml and select your feature branch. Click the 'Pull Request' button and fill out the form. Pull requests are usually reviewed within a few days.
|
78
|
+
|
79
|
+
#### Rebase
|
80
|
+
|
81
|
+
If you've been working on a change for a while, rebase with upstream/master.
|
82
|
+
|
83
|
+
```
|
84
|
+
git fetch upstream
|
85
|
+
git rebase upstream/master
|
86
|
+
git push origin my-feature-branch -f
|
87
|
+
```
|
88
|
+
|
89
|
+
#### Check on Your Pull Request
|
90
|
+
|
91
|
+
Go back to your pull request after a few minutes and see whether it passed muster with Travis-CI. Everything should look green, otherwise fix issues and amend your commit as described above.
|
92
|
+
|
93
|
+
#### Be Patient
|
94
|
+
|
95
|
+
It's likely that your change will not be merged and that the nitpicky maintainers will ask you to do more, or fix seemingly benign problems. Hang on there!
|
96
|
+
|
97
|
+
#### Thank You
|
98
|
+
|
99
|
+
Please do know that we really appreciate and value your time and work. We love you, really.
|
data/Gemfile
ADDED
data/MIT-LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2015 Zachary Scott
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,89 @@
|
|
1
|
+
# ActiveModel::Serializers::Xml
|
2
|
+
|
3
|
+
This gem provides XML serialization for your Active Model objects and Active Record models.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
gem 'activemodel-serializers-xml'
|
11
|
+
```
|
12
|
+
|
13
|
+
And then execute:
|
14
|
+
|
15
|
+
$ bundle
|
16
|
+
|
17
|
+
Or install it yourself as:
|
18
|
+
|
19
|
+
$ gem install activemodel-serializers-xml
|
20
|
+
|
21
|
+
## Usage
|
22
|
+
|
23
|
+
### ActiveModel::Serializers::Xml
|
24
|
+
|
25
|
+
To use the `ActiveModel::Serializers::Xml` you only need to change from
|
26
|
+
`ActiveModel::Serialization` to `ActiveModel::Serializers::Xml`.
|
27
|
+
|
28
|
+
```ruby
|
29
|
+
class Person
|
30
|
+
include ActiveModel::Serializers::Xml
|
31
|
+
|
32
|
+
attr_accessor :name
|
33
|
+
|
34
|
+
def attributes
|
35
|
+
{'name' => nil}
|
36
|
+
end
|
37
|
+
end
|
38
|
+
```
|
39
|
+
|
40
|
+
With the `to_xml` you have an XML representing the model.
|
41
|
+
|
42
|
+
```ruby
|
43
|
+
person = Person.new
|
44
|
+
person.to_xml # => "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<person>\n <name nil=\"true\"/>\n</person>\n"
|
45
|
+
person.name = "Bob"
|
46
|
+
person.to_xml # => "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<person>\n <name>Bob</name>\n</person>\n"
|
47
|
+
```
|
48
|
+
|
49
|
+
From an XML string you define the attributes of the model.
|
50
|
+
You need to have the `attributes=` method defined on your class:
|
51
|
+
|
52
|
+
```ruby
|
53
|
+
class Person
|
54
|
+
include ActiveModel::Serializers::Xml
|
55
|
+
|
56
|
+
attr_accessor :name
|
57
|
+
|
58
|
+
def attributes=(hash)
|
59
|
+
hash.each do |key, value|
|
60
|
+
send("#{key}=", value)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def attributes
|
65
|
+
{'name' => nil}
|
66
|
+
end
|
67
|
+
end
|
68
|
+
```
|
69
|
+
|
70
|
+
Now it is possible to create an instance of person and set the attributes using `from_xml`.
|
71
|
+
|
72
|
+
```ruby
|
73
|
+
xml = { name: 'Bob' }.to_xml
|
74
|
+
person = Person.new
|
75
|
+
person.from_xml(xml) # => #<Person:0x00000100c773f0 @name="Bob">
|
76
|
+
person.name # => "Bob"
|
77
|
+
```
|
78
|
+
|
79
|
+
### ActiveRecord::XmlSerializer
|
80
|
+
|
81
|
+
This gem also provides serialization to XML for Active Record.
|
82
|
+
|
83
|
+
Please see ActiveRecord::Serialization#to_xml for more information.
|
84
|
+
|
85
|
+
## Contributing to ActiveModel::Serializers::Xml
|
86
|
+
|
87
|
+
ActiveModel::Serializers::Xml is work of many contributors. You're encouraged to submit pull requests, propose features and discuss issues.
|
88
|
+
|
89
|
+
See [CONTRIBUTING](CONTRIBUTING.md)
|
data/Rakefile
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'active_model/serializers/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "activemodel-serializers-xml"
|
8
|
+
spec.version = ActiveModel::Serializers::VERSION
|
9
|
+
spec.authors = ["Zachary Scott"]
|
10
|
+
spec.email = ["e@zzak.io"]
|
11
|
+
|
12
|
+
spec.summary = "XML serialization for your Active Model objects and Active Record models - extracted from Rails"
|
13
|
+
spec.homepage = "http://github.com/rails/activemodel-serializers-xml"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
17
|
+
spec.require_paths = ["lib"]
|
18
|
+
spec.add_dependency "activesupport", "> 5.x"
|
19
|
+
spec.add_dependency "activemodel", "> 5.x"
|
20
|
+
spec.add_dependency "activerecord", "> 5.x"
|
21
|
+
spec.add_dependency "builder", "~> 3.1"
|
22
|
+
|
23
|
+
spec.add_development_dependency "bundler", "~> 1.9"
|
24
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
25
|
+
spec.add_development_dependency "sqlite3"
|
26
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'active_model/serializers'
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'active_support'
|
2
|
+
require 'active_support/lazy_load_hooks'
|
3
|
+
require 'active_record'
|
4
|
+
require 'active_model'
|
5
|
+
require "active_model/serializers/version"
|
6
|
+
|
7
|
+
ActiveSupport.on_load(:active_model) do
|
8
|
+
require "active_model/serializers/xml"
|
9
|
+
end
|
10
|
+
|
11
|
+
ActiveSupport.on_load(:active_record) do
|
12
|
+
require "active_record/serializers/xml_serializer"
|
13
|
+
end
|
14
|
+
|
15
|
+
module ActiveModel
|
16
|
+
module Serializers
|
17
|
+
extend ActiveSupport::Autoload
|
18
|
+
|
19
|
+
eager_autoload do
|
20
|
+
autoload :Xml
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.eager_load!
|
25
|
+
super
|
26
|
+
ActiveModel::Serializers.eager_load!
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,238 @@
|
|
1
|
+
require 'active_support/deprecation'
|
2
|
+
require 'active_support/core_ext/module/attribute_accessors'
|
3
|
+
require 'active_support/core_ext/array/conversions'
|
4
|
+
require 'active_support/core_ext/hash/conversions'
|
5
|
+
require 'active_support/core_ext/hash/slice'
|
6
|
+
require 'active_support/core_ext/time/acts_like'
|
7
|
+
|
8
|
+
module ActiveModel
|
9
|
+
module Serializers
|
10
|
+
module Xml
|
11
|
+
extend ActiveSupport::Concern
|
12
|
+
include ActiveModel::Serialization
|
13
|
+
|
14
|
+
included do
|
15
|
+
extend ActiveModel::Naming
|
16
|
+
end
|
17
|
+
|
18
|
+
class Serializer #:nodoc:
|
19
|
+
class Attribute #:nodoc:
|
20
|
+
attr_reader :name, :value, :type
|
21
|
+
|
22
|
+
def initialize(name, serializable, value)
|
23
|
+
@name, @serializable = name, serializable
|
24
|
+
|
25
|
+
if value.acts_like?(:time) && value.respond_to?(:in_time_zone)
|
26
|
+
value = value.in_time_zone
|
27
|
+
end
|
28
|
+
|
29
|
+
@value = value
|
30
|
+
@type = compute_type
|
31
|
+
end
|
32
|
+
|
33
|
+
def decorations
|
34
|
+
decorations = {}
|
35
|
+
decorations[:encoding] = 'base64' if type == :binary
|
36
|
+
decorations[:type] = (type == :string) ? nil : type
|
37
|
+
decorations[:nil] = true if value.nil?
|
38
|
+
decorations
|
39
|
+
end
|
40
|
+
|
41
|
+
protected
|
42
|
+
|
43
|
+
def compute_type
|
44
|
+
return if value.nil?
|
45
|
+
type = ActiveSupport::XmlMini::TYPE_NAMES[value.class.name]
|
46
|
+
type ||= :string if value.respond_to?(:to_str)
|
47
|
+
type ||= :yaml
|
48
|
+
type
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
class MethodAttribute < Attribute #:nodoc:
|
53
|
+
end
|
54
|
+
|
55
|
+
attr_reader :options
|
56
|
+
|
57
|
+
def initialize(serializable, options = nil)
|
58
|
+
@serializable = serializable
|
59
|
+
@options = options ? options.dup : {}
|
60
|
+
end
|
61
|
+
|
62
|
+
def serializable_hash
|
63
|
+
@serializable.serializable_hash(@options.except(:include))
|
64
|
+
end
|
65
|
+
|
66
|
+
def serializable_collection
|
67
|
+
methods = Array(options[:methods]).map(&:to_s)
|
68
|
+
serializable_hash.map do |name, value|
|
69
|
+
name = name.to_s
|
70
|
+
if methods.include?(name)
|
71
|
+
self.class::MethodAttribute.new(name, @serializable, value)
|
72
|
+
else
|
73
|
+
self.class::Attribute.new(name, @serializable, value)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def serialize
|
79
|
+
require 'builder' unless defined? ::Builder
|
80
|
+
|
81
|
+
options[:indent] ||= 2
|
82
|
+
options[:builder] ||= ::Builder::XmlMarkup.new(indent: options[:indent])
|
83
|
+
|
84
|
+
@builder = options[:builder]
|
85
|
+
@builder.instruct! unless options[:skip_instruct]
|
86
|
+
|
87
|
+
root = (options[:root] || @serializable.model_name.element).to_s
|
88
|
+
root = ActiveSupport::XmlMini.rename_key(root, options)
|
89
|
+
|
90
|
+
args = [root]
|
91
|
+
args << { xmlns: options[:namespace] } if options[:namespace]
|
92
|
+
args << { type: options[:type] } if options[:type] && !options[:skip_types]
|
93
|
+
|
94
|
+
@builder.tag!(*args) do
|
95
|
+
add_attributes_and_methods
|
96
|
+
add_includes
|
97
|
+
add_extra_behavior
|
98
|
+
add_procs
|
99
|
+
yield @builder if block_given?
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
private
|
104
|
+
|
105
|
+
def add_extra_behavior
|
106
|
+
end
|
107
|
+
|
108
|
+
def add_attributes_and_methods
|
109
|
+
serializable_collection.each do |attribute|
|
110
|
+
key = ActiveSupport::XmlMini.rename_key(attribute.name, options)
|
111
|
+
ActiveSupport::XmlMini.to_tag(key, attribute.value,
|
112
|
+
options.merge(attribute.decorations))
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
def add_includes
|
117
|
+
@serializable.send(:serializable_add_includes, options) do |association, records, opts|
|
118
|
+
add_associations(association, records, opts)
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
# TODO: This can likely be cleaned up to simple use ActiveSupport::XmlMini.to_tag as well.
|
123
|
+
def add_associations(association, records, opts)
|
124
|
+
merged_options = opts.merge(options.slice(:builder, :indent))
|
125
|
+
merged_options[:skip_instruct] = true
|
126
|
+
|
127
|
+
[:skip_types, :dasherize, :camelize].each do |key|
|
128
|
+
merged_options[key] = options[key] if merged_options[key].nil? && !options[key].nil?
|
129
|
+
end
|
130
|
+
|
131
|
+
if records.respond_to?(:to_ary)
|
132
|
+
records = records.to_ary
|
133
|
+
|
134
|
+
tag = ActiveSupport::XmlMini.rename_key(association.to_s, options)
|
135
|
+
type = options[:skip_types] ? { } : { type: "array" }
|
136
|
+
association_name = association.to_s.singularize
|
137
|
+
merged_options[:root] = association_name
|
138
|
+
|
139
|
+
if records.empty?
|
140
|
+
@builder.tag!(tag, type)
|
141
|
+
else
|
142
|
+
@builder.tag!(tag, type) do
|
143
|
+
records.each do |record|
|
144
|
+
if options[:skip_types]
|
145
|
+
record_type = {}
|
146
|
+
else
|
147
|
+
record_class = (record.class.to_s.underscore == association_name) ? nil : record.class.name
|
148
|
+
record_type = { type: record_class }
|
149
|
+
end
|
150
|
+
|
151
|
+
record.to_xml merged_options.merge(record_type)
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
155
|
+
else
|
156
|
+
merged_options[:root] = association.to_s
|
157
|
+
|
158
|
+
unless records.class.to_s.underscore == association.to_s
|
159
|
+
merged_options[:type] = records.class.name
|
160
|
+
end
|
161
|
+
|
162
|
+
records.to_xml merged_options
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
def add_procs
|
167
|
+
if procs = options.delete(:procs)
|
168
|
+
Array(procs).each do |proc|
|
169
|
+
if proc.arity == 1
|
170
|
+
proc.call(options)
|
171
|
+
else
|
172
|
+
proc.call(options, @serializable)
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
# Returns XML representing the model. Configuration can be
|
180
|
+
# passed through +options+.
|
181
|
+
#
|
182
|
+
# Without any +options+, the returned XML string will include all the
|
183
|
+
# model's attributes.
|
184
|
+
#
|
185
|
+
# user = User.find(1)
|
186
|
+
# user.to_xml
|
187
|
+
#
|
188
|
+
# <?xml version="1.0" encoding="UTF-8"?>
|
189
|
+
# <user>
|
190
|
+
# <id type="integer">1</id>
|
191
|
+
# <name>David</name>
|
192
|
+
# <age type="integer">16</age>
|
193
|
+
# <created-at type="dateTime">2011-01-30T22:29:23Z</created-at>
|
194
|
+
# </user>
|
195
|
+
#
|
196
|
+
# The <tt>:only</tt> and <tt>:except</tt> options can be used to limit the
|
197
|
+
# attributes included, and work similar to the +attributes+ method.
|
198
|
+
#
|
199
|
+
# To include the result of some method calls on the model use <tt>:methods</tt>.
|
200
|
+
#
|
201
|
+
# To include associations use <tt>:include</tt>.
|
202
|
+
#
|
203
|
+
# For further documentation, see <tt>ActiveRecord::Serialization#to_xml</tt>
|
204
|
+
def to_xml(options = {}, &block)
|
205
|
+
Serializer.new(self, options).serialize(&block)
|
206
|
+
end
|
207
|
+
|
208
|
+
# Sets the model +attributes+ from an XML string. Returns +self+.
|
209
|
+
#
|
210
|
+
# class Person
|
211
|
+
# include ActiveModel::Serializers::Xml
|
212
|
+
#
|
213
|
+
# attr_accessor :name, :age, :awesome
|
214
|
+
#
|
215
|
+
# def attributes=(hash)
|
216
|
+
# hash.each do |key, value|
|
217
|
+
# instance_variable_set("@#{key}", value)
|
218
|
+
# end
|
219
|
+
# end
|
220
|
+
#
|
221
|
+
# def attributes
|
222
|
+
# instance_values
|
223
|
+
# end
|
224
|
+
# end
|
225
|
+
#
|
226
|
+
# xml = { name: 'bob', age: 22, awesome:true }.to_xml
|
227
|
+
# person = Person.new
|
228
|
+
# person.from_xml(xml) # => #<Person:0x007fec5e3b3c40 @age=22, @awesome=true, @name="bob">
|
229
|
+
# person.name # => "bob"
|
230
|
+
# person.age # => 22
|
231
|
+
# person.awesome # => true
|
232
|
+
def from_xml(xml)
|
233
|
+
self.attributes = Hash.from_xml(xml).values.first
|
234
|
+
self
|
235
|
+
end
|
236
|
+
end
|
237
|
+
end
|
238
|
+
end
|
@@ -0,0 +1,194 @@
|
|
1
|
+
require 'active_support/core_ext/hash/conversions'
|
2
|
+
require 'active_model/serializers/xml'
|
3
|
+
|
4
|
+
module ActiveRecord #:nodoc:
|
5
|
+
module Serialization
|
6
|
+
include ActiveModel::Serializers::Xml
|
7
|
+
|
8
|
+
# Builds an XML document to represent the model. Some configuration is
|
9
|
+
# available through +options+. However more complicated cases should
|
10
|
+
# override ActiveRecord::Base#to_xml.
|
11
|
+
#
|
12
|
+
# By default the generated XML document will include the processing
|
13
|
+
# instruction and all the object's attributes. For example:
|
14
|
+
#
|
15
|
+
# <?xml version="1.0" encoding="UTF-8"?>
|
16
|
+
# <topic>
|
17
|
+
# <title>The First Topic</title>
|
18
|
+
# <author-name>David</author-name>
|
19
|
+
# <id type="integer">1</id>
|
20
|
+
# <approved type="boolean">false</approved>
|
21
|
+
# <replies-count type="integer">0</replies-count>
|
22
|
+
# <bonus-time type="dateTime">2000-01-01T08:28:00+12:00</bonus-time>
|
23
|
+
# <written-on type="dateTime">2003-07-16T09:28:00+1200</written-on>
|
24
|
+
# <content>Have a nice day</content>
|
25
|
+
# <author-email-address>david@loudthinking.com</author-email-address>
|
26
|
+
# <parent-id></parent-id>
|
27
|
+
# <last-read type="date">2004-04-15</last-read>
|
28
|
+
# </topic>
|
29
|
+
#
|
30
|
+
# This behavior can be controlled with <tt>:only</tt>, <tt>:except</tt>,
|
31
|
+
# <tt>:skip_instruct</tt>, <tt>:skip_types</tt>, <tt>:dasherize</tt> and <tt>:camelize</tt> .
|
32
|
+
# The <tt>:only</tt> and <tt>:except</tt> options are the same as for the
|
33
|
+
# +attributes+ method. The default is to dasherize all column names, but you
|
34
|
+
# can disable this setting <tt>:dasherize</tt> to +false+. Setting <tt>:camelize</tt>
|
35
|
+
# to +true+ will camelize all column names - this also overrides <tt>:dasherize</tt>.
|
36
|
+
# To not have the column type included in the XML output set <tt>:skip_types</tt> to +true+.
|
37
|
+
#
|
38
|
+
# For instance:
|
39
|
+
#
|
40
|
+
# topic.to_xml(skip_instruct: true, except: [ :id, :bonus_time, :written_on, :replies_count ])
|
41
|
+
#
|
42
|
+
# <topic>
|
43
|
+
# <title>The First Topic</title>
|
44
|
+
# <author-name>David</author-name>
|
45
|
+
# <approved type="boolean">false</approved>
|
46
|
+
# <content>Have a nice day</content>
|
47
|
+
# <author-email-address>david@loudthinking.com</author-email-address>
|
48
|
+
# <parent-id></parent-id>
|
49
|
+
# <last-read type="date">2004-04-15</last-read>
|
50
|
+
# </topic>
|
51
|
+
#
|
52
|
+
# To include first level associations use <tt>:include</tt>:
|
53
|
+
#
|
54
|
+
# firm.to_xml include: [ :account, :clients ]
|
55
|
+
#
|
56
|
+
# <?xml version="1.0" encoding="UTF-8"?>
|
57
|
+
# <firm>
|
58
|
+
# <id type="integer">1</id>
|
59
|
+
# <rating type="integer">1</rating>
|
60
|
+
# <name>37signals</name>
|
61
|
+
# <clients type="array">
|
62
|
+
# <client>
|
63
|
+
# <rating type="integer">1</rating>
|
64
|
+
# <name>Summit</name>
|
65
|
+
# </client>
|
66
|
+
# <client>
|
67
|
+
# <rating type="integer">1</rating>
|
68
|
+
# <name>Microsoft</name>
|
69
|
+
# </client>
|
70
|
+
# </clients>
|
71
|
+
# <account>
|
72
|
+
# <id type="integer">1</id>
|
73
|
+
# <credit-limit type="integer">50</credit-limit>
|
74
|
+
# </account>
|
75
|
+
# </firm>
|
76
|
+
#
|
77
|
+
# Additionally, the record being serialized will be passed to a Proc's second
|
78
|
+
# parameter. This allows for ad hoc additions to the resultant document that
|
79
|
+
# incorporate the context of the record being serialized. And by leveraging the
|
80
|
+
# closure created by a Proc, to_xml can be used to add elements that normally fall
|
81
|
+
# outside of the scope of the model -- for example, generating and appending URLs
|
82
|
+
# associated with models.
|
83
|
+
#
|
84
|
+
# proc = Proc.new { |options, record| options[:builder].tag!('name-reverse', record.name.reverse) }
|
85
|
+
# firm.to_xml procs: [ proc ]
|
86
|
+
#
|
87
|
+
# <firm>
|
88
|
+
# # ... normal attributes as shown above ...
|
89
|
+
# <name-reverse>slangis73</name-reverse>
|
90
|
+
# </firm>
|
91
|
+
#
|
92
|
+
# To include deeper levels of associations pass a hash like this:
|
93
|
+
#
|
94
|
+
# firm.to_xml include: {account: {}, clients: {include: :address}}
|
95
|
+
# <?xml version="1.0" encoding="UTF-8"?>
|
96
|
+
# <firm>
|
97
|
+
# <id type="integer">1</id>
|
98
|
+
# <rating type="integer">1</rating>
|
99
|
+
# <name>37signals</name>
|
100
|
+
# <clients type="array">
|
101
|
+
# <client>
|
102
|
+
# <rating type="integer">1</rating>
|
103
|
+
# <name>Summit</name>
|
104
|
+
# <address>
|
105
|
+
# ...
|
106
|
+
# </address>
|
107
|
+
# </client>
|
108
|
+
# <client>
|
109
|
+
# <rating type="integer">1</rating>
|
110
|
+
# <name>Microsoft</name>
|
111
|
+
# <address>
|
112
|
+
# ...
|
113
|
+
# </address>
|
114
|
+
# </client>
|
115
|
+
# </clients>
|
116
|
+
# <account>
|
117
|
+
# <id type="integer">1</id>
|
118
|
+
# <credit-limit type="integer">50</credit-limit>
|
119
|
+
# </account>
|
120
|
+
# </firm>
|
121
|
+
#
|
122
|
+
# To include any methods on the model being called use <tt>:methods</tt>:
|
123
|
+
#
|
124
|
+
# firm.to_xml methods: [ :calculated_earnings, :real_earnings ]
|
125
|
+
#
|
126
|
+
# <firm>
|
127
|
+
# # ... normal attributes as shown above ...
|
128
|
+
# <calculated-earnings>100000000000000000</calculated-earnings>
|
129
|
+
# <real-earnings>5</real-earnings>
|
130
|
+
# </firm>
|
131
|
+
#
|
132
|
+
# To call any additional Procs use <tt>:procs</tt>. The Procs are passed a
|
133
|
+
# modified version of the options hash that was given to +to_xml+:
|
134
|
+
#
|
135
|
+
# proc = Proc.new { |options| options[:builder].tag!('abc', 'def') }
|
136
|
+
# firm.to_xml procs: [ proc ]
|
137
|
+
#
|
138
|
+
# <firm>
|
139
|
+
# # ... normal attributes as shown above ...
|
140
|
+
# <abc>def</abc>
|
141
|
+
# </firm>
|
142
|
+
#
|
143
|
+
# Alternatively, you can yield the builder object as part of the +to_xml+ call:
|
144
|
+
#
|
145
|
+
# firm.to_xml do |xml|
|
146
|
+
# xml.creator do
|
147
|
+
# xml.first_name "David"
|
148
|
+
# xml.last_name "Heinemeier Hansson"
|
149
|
+
# end
|
150
|
+
# end
|
151
|
+
#
|
152
|
+
# <firm>
|
153
|
+
# # ... normal attributes as shown above ...
|
154
|
+
# <creator>
|
155
|
+
# <first_name>David</first_name>
|
156
|
+
# <last_name>Heinemeier Hansson</last_name>
|
157
|
+
# </creator>
|
158
|
+
# </firm>
|
159
|
+
#
|
160
|
+
# As noted above, you may override +to_xml+ in your ActiveRecord::Base
|
161
|
+
# subclasses to have complete control about what's generated. The general
|
162
|
+
# form of doing this is:
|
163
|
+
#
|
164
|
+
# class IHaveMyOwnXML < ActiveRecord::Base
|
165
|
+
# def to_xml(options = {})
|
166
|
+
# require 'builder'
|
167
|
+
# options[:indent] ||= 2
|
168
|
+
# xml = options[:builder] ||= ::Builder::XmlMarkup.new(indent: options[:indent])
|
169
|
+
# xml.instruct! unless options[:skip_instruct]
|
170
|
+
# xml.level_one do
|
171
|
+
# xml.tag!(:second_level, 'content')
|
172
|
+
# end
|
173
|
+
# end
|
174
|
+
# end
|
175
|
+
def to_xml(options = {}, &block)
|
176
|
+
XmlSerializer.new(self, options).serialize(&block)
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
class XmlSerializer < ActiveModel::Serializers::Xml::Serializer #:nodoc:
|
181
|
+
class Attribute < ActiveModel::Serializers::Xml::Serializer::Attribute #:nodoc:
|
182
|
+
def compute_type
|
183
|
+
klass = @serializable.class
|
184
|
+
cast_type = klass.type_for_attribute(name)
|
185
|
+
|
186
|
+
type = ActiveSupport::XmlMini::TYPE_NAMES[value.class.name] || cast_type.type
|
187
|
+
|
188
|
+
{ :text => :string,
|
189
|
+
:time => :datetime }[type] || type
|
190
|
+
end
|
191
|
+
protected :compute_type
|
192
|
+
end
|
193
|
+
end
|
194
|
+
end
|
metadata
ADDED
@@ -0,0 +1,156 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: activemodel-serializers-xml
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Zachary Scott
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-02-05 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: activesupport
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 5.x
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 5.x
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: activemodel
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 5.x
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 5.x
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: activerecord
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 5.x
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 5.x
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: builder
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '3.1'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '3.1'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: bundler
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '1.9'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '1.9'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rake
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '10.0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '10.0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: sqlite3
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
description:
|
112
|
+
email:
|
113
|
+
- e@zzak.io
|
114
|
+
executables: []
|
115
|
+
extensions: []
|
116
|
+
extra_rdoc_files: []
|
117
|
+
files:
|
118
|
+
- ".gitignore"
|
119
|
+
- ".travis.yml"
|
120
|
+
- CONTRIBUTING.md
|
121
|
+
- Gemfile
|
122
|
+
- MIT-LICENSE
|
123
|
+
- README.md
|
124
|
+
- Rakefile
|
125
|
+
- activemodel-serializers-xml.gemspec
|
126
|
+
- lib/active_model-serializers.rb
|
127
|
+
- lib/active_model/serializers.rb
|
128
|
+
- lib/active_model/serializers/version.rb
|
129
|
+
- lib/active_model/serializers/xml.rb
|
130
|
+
- lib/active_record/serializers/xml_serializer.rb
|
131
|
+
homepage: http://github.com/rails/activemodel-serializers-xml
|
132
|
+
licenses:
|
133
|
+
- MIT
|
134
|
+
metadata: {}
|
135
|
+
post_install_message:
|
136
|
+
rdoc_options: []
|
137
|
+
require_paths:
|
138
|
+
- lib
|
139
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
140
|
+
requirements:
|
141
|
+
- - ">="
|
142
|
+
- !ruby/object:Gem::Version
|
143
|
+
version: '0'
|
144
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
145
|
+
requirements:
|
146
|
+
- - ">="
|
147
|
+
- !ruby/object:Gem::Version
|
148
|
+
version: '0'
|
149
|
+
requirements: []
|
150
|
+
rubyforge_project:
|
151
|
+
rubygems_version: 2.5.1
|
152
|
+
signing_key:
|
153
|
+
specification_version: 4
|
154
|
+
summary: XML serialization for your Active Model objects and Active Record models
|
155
|
+
- extracted from Rails
|
156
|
+
test_files: []
|