Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
张重言
rails
提交
9645820b
R
rails
项目概览
张重言
/
rails
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
rails
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
9645820b
编写于
8月 07, 2015
作者:
R
Rafael Mendonça França
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #21161 from rails/rm-xml-serializer
Remove XML Serialization from core
上级
752432e8
f7ebdb1a
变更
13
显示空白变更内容
内联
并排
Showing
13 changed file
with
12 addition
and
1204 deletion
+12
-1204
activemodel/CHANGELOG.md
activemodel/CHANGELOG.md
+4
-0
activemodel/README.rdoc
activemodel/README.rdoc
+1
-8
activemodel/lib/active_model.rb
activemodel/lib/active_model.rb
+0
-1
activemodel/lib/active_model/serialization.rb
activemodel/lib/active_model/serialization.rb
+0
-3
activemodel/lib/active_model/serializers/xml.rb
activemodel/lib/active_model/serializers/xml.rb
+0
-238
activemodel/test/cases/serializers/xml_serialization_test.rb
activemodel/test/cases/serializers/xml_serialization_test.rb
+0
-251
activemodel/test/models/contact.rb
activemodel/test/models/contact.rb
+0
-1
activerecord/CHANGELOG.md
activerecord/CHANGELOG.md
+4
-0
activerecord/lib/active_record/serialization.rb
activerecord/lib/active_record/serialization.rb
+0
-2
activerecord/lib/active_record/serializers/xml_serializer.rb
activerecord/lib/active_record/serializers/xml_serializer.rb
+0
-193
activerecord/test/cases/serialization_test.rb
activerecord/test/cases/serialization_test.rb
+1
-1
activerecord/test/cases/xml_serialization_test.rb
activerecord/test/cases/xml_serialization_test.rb
+0
-447
guides/source/active_model_basics.md
guides/source/active_model_basics.md
+2
-59
未找到文件。
activemodel/CHANGELOG.md
浏览文件 @
9645820b
...
...
@@ -3,6 +3,10 @@
*Jay Elaraj*
*
Remove
`ActiveModel::Serializers::Xml`
from core.
*Zachary Scott*
*
Add
`ActiveModel::Dirty#[attr_name]_previously_changed?`
and
`ActiveModel::Dirty#[attr_name]_previous_change`
to improve access
to recorded changes after the model has been saved.
...
...
activemodel/README.rdoc
浏览文件 @
9645820b
...
...
@@ -155,7 +155,7 @@ behavior out of the box:
* Making objects serializable
<tt>ActiveModel::Serialization</tt> provides a standard interface for your object
to provide +to_json+
or +to_xml+
serialization.
to provide +to_json+ serialization.
class SerialPerson
include ActiveModel::Serialization
...
...
@@ -177,13 +177,6 @@ behavior out of the box:
s = SerialPerson.new
s.to_json # => "{\"name\":null}"
class SerialPerson
include ActiveModel::Serializers::Xml
end
s = SerialPerson.new
s.to_xml # => "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<serial-person...
{Learn more}[link:classes/ActiveModel/Serialization.html]
* Internationalization (i18n) support
...
...
activemodel/lib/active_model.rb
浏览文件 @
9645820b
...
...
@@ -58,7 +58,6 @@ module Serializers
eager_autoload
do
autoload
:JSON
autoload
:Xml
end
end
...
...
activemodel/lib/active_model/serialization.rb
浏览文件 @
9645820b
...
...
@@ -40,7 +40,6 @@ module ActiveModel
#
# class Person
# include ActiveModel::Serializers::JSON
# include ActiveModel::Serializers::Xml
#
# attr_accessor :name
#
...
...
@@ -55,13 +54,11 @@ module ActiveModel
# person.serializable_hash # => {"name"=>nil}
# person.as_json # => {"name"=>nil}
# person.to_json # => "{\"name\":null}"
# person.to_xml # => "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<serial-person...
#
# person.name = "Bob"
# person.serializable_hash # => {"name"=>"Bob"}
# person.as_json # => {"name"=>"Bob"}
# person.to_json # => "{\"name\":\"Bob\"}"
# person.to_xml # => "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<serial-person...
#
# Valid options are <tt>:only</tt>, <tt>:except</tt>, <tt>:methods</tt> and
# <tt>:include</tt>. The following are all valid examples:
...
...
activemodel/lib/active_model/serializers/xml.rb
已删除
100644 → 0
浏览文件 @
752432e8
require
'active_support/core_ext/module/attribute_accessors'
require
'active_support/core_ext/array/conversions'
require
'active_support/core_ext/hash/conversions'
require
'active_support/core_ext/hash/slice'
require
'active_support/core_ext/time/acts_like'
module
ActiveModel
module
Serializers
# == \Active \Model XML Serializer
module
Xml
extend
ActiveSupport
::
Concern
include
ActiveModel
::
Serialization
included
do
extend
ActiveModel
::
Naming
end
class
Serializer
#:nodoc:
class
Attribute
#:nodoc:
attr_reader
:name
,
:value
,
:type
def
initialize
(
name
,
serializable
,
value
)
@name
,
@serializable
=
name
,
serializable
if
value
.
acts_like?
(
:time
)
&&
value
.
respond_to?
(
:in_time_zone
)
value
=
value
.
in_time_zone
end
@value
=
value
@type
=
compute_type
end
def
decorations
decorations
=
{}
decorations
[
:encoding
]
=
'base64'
if
type
==
:binary
decorations
[
:type
]
=
(
type
==
:string
)
?
nil
:
type
decorations
[
:nil
]
=
true
if
value
.
nil?
decorations
end
protected
def
compute_type
return
if
value
.
nil?
type
=
ActiveSupport
::
XmlMini
::
TYPE_NAMES
[
value
.
class
.
name
]
type
||=
:string
if
value
.
respond_to?
(
:to_str
)
type
||=
:yaml
type
end
end
class
MethodAttribute
<
Attribute
#:nodoc:
end
attr_reader
:options
def
initialize
(
serializable
,
options
=
nil
)
@serializable
=
serializable
@options
=
options
?
options
.
dup
:
{}
end
def
serializable_hash
@serializable
.
serializable_hash
(
@options
.
except
(
:include
))
end
def
serializable_collection
methods
=
Array
(
options
[
:methods
]).
map
(
&
:to_s
)
serializable_hash
.
map
do
|
name
,
value
|
name
=
name
.
to_s
if
methods
.
include?
(
name
)
self
.
class
::
MethodAttribute
.
new
(
name
,
@serializable
,
value
)
else
self
.
class
::
Attribute
.
new
(
name
,
@serializable
,
value
)
end
end
end
def
serialize
require
'builder'
unless
defined?
::
Builder
options
[
:indent
]
||=
2
options
[
:builder
]
||=
::
Builder
::
XmlMarkup
.
new
(
indent:
options
[
:indent
])
@builder
=
options
[
:builder
]
@builder
.
instruct!
unless
options
[
:skip_instruct
]
root
=
(
options
[
:root
]
||
@serializable
.
model_name
.
element
).
to_s
root
=
ActiveSupport
::
XmlMini
.
rename_key
(
root
,
options
)
args
=
[
root
]
args
<<
{
xmlns:
options
[
:namespace
]
}
if
options
[
:namespace
]
args
<<
{
type:
options
[
:type
]
}
if
options
[
:type
]
&&
!
options
[
:skip_types
]
@builder
.
tag!
(
*
args
)
do
add_attributes_and_methods
add_includes
add_extra_behavior
add_procs
yield
@builder
if
block_given?
end
end
private
def
add_extra_behavior
end
def
add_attributes_and_methods
serializable_collection
.
each
do
|
attribute
|
key
=
ActiveSupport
::
XmlMini
.
rename_key
(
attribute
.
name
,
options
)
ActiveSupport
::
XmlMini
.
to_tag
(
key
,
attribute
.
value
,
options
.
merge
(
attribute
.
decorations
))
end
end
def
add_includes
@serializable
.
send
(
:serializable_add_includes
,
options
)
do
|
association
,
records
,
opts
|
add_associations
(
association
,
records
,
opts
)
end
end
# TODO: This can likely be cleaned up to simple use ActiveSupport::XmlMini.to_tag as well.
def
add_associations
(
association
,
records
,
opts
)
merged_options
=
opts
.
merge
(
options
.
slice
(
:builder
,
:indent
))
merged_options
[
:skip_instruct
]
=
true
[
:skip_types
,
:dasherize
,
:camelize
].
each
do
|
key
|
merged_options
[
key
]
=
options
[
key
]
if
merged_options
[
key
].
nil?
&&
!
options
[
key
].
nil?
end
if
records
.
respond_to?
(
:to_ary
)
records
=
records
.
to_ary
tag
=
ActiveSupport
::
XmlMini
.
rename_key
(
association
.
to_s
,
options
)
type
=
options
[
:skip_types
]
?
{
}
:
{
type:
"array"
}
association_name
=
association
.
to_s
.
singularize
merged_options
[
:root
]
=
association_name
if
records
.
empty?
@builder
.
tag!
(
tag
,
type
)
else
@builder
.
tag!
(
tag
,
type
)
do
records
.
each
do
|
record
|
if
options
[
:skip_types
]
record_type
=
{}
else
record_class
=
(
record
.
class
.
to_s
.
underscore
==
association_name
)
?
nil
:
record
.
class
.
name
record_type
=
{
type:
record_class
}
end
record
.
to_xml
merged_options
.
merge
(
record_type
)
end
end
end
else
merged_options
[
:root
]
=
association
.
to_s
unless
records
.
class
.
to_s
.
underscore
==
association
.
to_s
merged_options
[
:type
]
=
records
.
class
.
name
end
records
.
to_xml
merged_options
end
end
def
add_procs
if
procs
=
options
.
delete
(
:procs
)
Array
(
procs
).
each
do
|
proc
|
if
proc
.
arity
==
1
proc
.
call
(
options
)
else
proc
.
call
(
options
,
@serializable
)
end
end
end
end
end
# Returns XML representing the model. Configuration can be
# passed through +options+.
#
# Without any +options+, the returned XML string will include all the
# model's attributes.
#
# user = User.find(1)
# user.to_xml
#
# <?xml version="1.0" encoding="UTF-8"?>
# <user>
# <id type="integer">1</id>
# <name>David</name>
# <age type="integer">16</age>
# <created-at type="dateTime">2011-01-30T22:29:23Z</created-at>
# </user>
#
# The <tt>:only</tt> and <tt>:except</tt> options can be used to limit the
# attributes included, and work similar to the +attributes+ method.
#
# To include the result of some method calls on the model use <tt>:methods</tt>.
#
# To include associations use <tt>:include</tt>.
#
# For further documentation, see <tt>ActiveRecord::Serialization#to_xml</tt>
def
to_xml
(
options
=
{},
&
block
)
Serializer
.
new
(
self
,
options
).
serialize
(
&
block
)
end
# Sets the model +attributes+ from an XML string. Returns +self+.
#
# class Person
# include ActiveModel::Serializers::Xml
#
# attr_accessor :name, :age, :awesome
#
# def attributes=(hash)
# hash.each do |key, value|
# instance_variable_set("@#{key}", value)
# end
# end
#
# def attributes
# instance_values
# end
# end
#
# xml = { name: 'bob', age: 22, awesome:true }.to_xml
# person = Person.new
# person.from_xml(xml) # => #<Person:0x007fec5e3b3c40 @age=22, @awesome=true, @name="bob">
# person.name # => "bob"
# person.age # => 22
# person.awesome # => true
def
from_xml
(
xml
)
self
.
attributes
=
Hash
.
from_xml
(
xml
).
values
.
first
self
end
end
end
end
activemodel/test/cases/serializers/xml_serialization_test.rb
已删除
100644 → 0
浏览文件 @
752432e8
require
'cases/helper'
require
'models/contact'
require
'active_support/core_ext/object/instance_variables'
require
'ostruct'
require
'yaml'
module
Admin
class
Contact
<
::
Contact
end
end
class
Customer
<
Struct
.
new
(
:name
)
end
class
Address
include
ActiveModel
::
Serializers
::
Xml
attr_accessor
:street
,
:city
,
:state
,
:zip
,
:apt_number
def
attributes
instance_values
end
end
class
SerializableContact
<
Contact
def
serializable_hash
(
options
=
{})
super
(
options
.
merge
(
only:
[
:name
,
:age
]))
end
end
class
XmlSerializationTest
<
ActiveModel
::
TestCase
def
setup
@contact
=
Contact
.
new
@contact
.
name
=
'aaron stack'
@contact
.
age
=
25
@contact
.
created_at
=
Time
.
utc
(
2006
,
8
,
1
)
@contact
.
awesome
=
false
customer
=
Customer
.
new
customer
.
name
=
"John"
@contact
.
preferences
=
customer
@contact
.
address
=
Address
.
new
@contact
.
address
.
city
=
"Springfield"
@contact
.
address
.
apt_number
=
35
@contact
.
friends
=
[
Contact
.
new
,
Contact
.
new
]
@contact
.
contact
=
SerializableContact
.
new
end
test
"should serialize default root"
do
xml
=
@contact
.
to_xml
assert_match
%r{^<contact>}
,
xml
assert_match
%r{</contact>$}
,
xml
end
test
"should serialize namespaced root"
do
xml
=
Admin
::
Contact
.
new
(
@contact
.
attributes
).
to_xml
assert_match
%r{^<contact>}
,
xml
assert_match
%r{</contact>$}
,
xml
end
test
"should serialize default root with namespace"
do
xml
=
@contact
.
to_xml
namespace:
"http://xml.rubyonrails.org/contact"
assert_match
%r{^<contact xmlns="http://xml.rubyonrails.org/contact">}
,
xml
assert_match
%r{</contact>$}
,
xml
end
test
"should serialize custom root"
do
xml
=
@contact
.
to_xml
root:
'xml_contact'
assert_match
%r{^<xml-contact>}
,
xml
assert_match
%r{</xml-contact>$}
,
xml
end
test
"should allow undasherized tags"
do
xml
=
@contact
.
to_xml
root:
'xml_contact'
,
dasherize:
false
assert_match
%r{^<xml_contact>}
,
xml
assert_match
%r{</xml_contact>$}
,
xml
assert_match
%r{<created_at}
,
xml
end
test
"should allow camelized tags"
do
xml
=
@contact
.
to_xml
root:
'xml_contact'
,
camelize:
true
assert_match
%r{^<XmlContact>}
,
xml
assert_match
%r{</XmlContact>$}
,
xml
assert_match
%r{<CreatedAt}
,
xml
end
test
"should allow lower-camelized tags"
do
xml
=
@contact
.
to_xml
root:
'xml_contact'
,
camelize: :lower
assert_match
%r{^<xmlContact>}
,
xml
assert_match
%r{</xmlContact>$}
,
xml
assert_match
%r{<createdAt}
,
xml
end
test
"should use serializable hash"
do
@contact
=
SerializableContact
.
new
@contact
.
name
=
'aaron stack'
@contact
.
age
=
25
xml
=
@contact
.
to_xml
assert_match
%r{<name>aaron stack</name>}
,
xml
assert_match
%r{<age type="integer">25</age>}
,
xml
assert_no_match
%r{<awesome>}
,
xml
end
test
"should allow skipped types"
do
xml
=
@contact
.
to_xml
skip_types:
true
assert_match
%r{<age>25</age>}
,
xml
end
test
"should include yielded additions"
do
xml_output
=
@contact
.
to_xml
do
|
xml
|
xml
.
creator
"David"
end
assert_match
%r{<creator>David</creator>}
,
xml_output
end
test
"should serialize string"
do
assert_match
%r{<name>aaron stack</name>}
,
@contact
.
to_xml
end
test
"should serialize nil"
do
assert_match
%r{<pseudonyms nil="true"/>}
,
@contact
.
to_xml
(
methods: :pseudonyms
)
end
test
"should serialize integer"
do
assert_match
%r{<age type="integer">25</age>}
,
@contact
.
to_xml
end
test
"should serialize datetime"
do
assert_match
%r{<created-at type="dateTime">2006-08-01T00:00:00Z</created-at>}
,
@contact
.
to_xml
end
test
"should serialize boolean"
do
assert_match
%r{<awesome type="boolean">false</awesome>}
,
@contact
.
to_xml
end
test
"should serialize array"
do
assert_match
%r{<social type="array">
\s
*<social>twitter</social>
\s
*<social>github</social>
\s
*</social>}
,
@contact
.
to_xml
(
methods: :social
)
end
test
"should serialize hash"
do
assert_match
%r{<network>
\s
*<git type="symbol">github</git>
\s
*</network>}
,
@contact
.
to_xml
(
methods: :network
)
end
test
"should serialize yaml"
do
assert_match
%r{<preferences type="yaml">--- !ruby/struct:Customer(
\s
*)
\n
name: John
\n
</preferences>}
,
@contact
.
to_xml
end
test
"should call proc on object"
do
proc
=
Proc
.
new
{
|
options
|
options
[
:builder
].
tag!
(
'nationality'
,
'unknown'
)
}
xml
=
@contact
.
to_xml
(
procs:
[
proc
])
assert_match
%r{<nationality>unknown</nationality>}
,
xml
end
test
"should supply serializable to second proc argument"
do
proc
=
Proc
.
new
{
|
options
,
record
|
options
[
:builder
].
tag!
(
'name-reverse'
,
record
.
name
.
reverse
)
}
xml
=
@contact
.
to_xml
(
procs:
[
proc
])
assert_match
%r{<name-reverse>kcats noraa</name-reverse>}
,
xml
end
test
"should serialize string correctly when type passed"
do
xml
=
@contact
.
to_xml
type:
'Contact'
assert_match
%r{<contact type="Contact">}
,
xml
assert_match
%r{<name>aaron stack</name>}
,
xml
end
test
"include option with singular association"
do
xml
=
@contact
.
to_xml
include: :address
,
indent:
0
assert
xml
.
include?
(
@contact
.
address
.
to_xml
(
indent:
0
,
skip_instruct:
true
))
end
test
"include option with plural association"
do
xml
=
@contact
.
to_xml
include: :friends
,
indent:
0
assert_match
%r{<friends type="array">}
,
xml
assert_match
%r{<friend type="Contact">}
,
xml
end
class
FriendList
def
initialize
(
friends
)
@friends
=
friends
end
def
to_ary
@friends
end
end
test
"include option with ary"
do
@contact
.
friends
=
FriendList
.
new
(
@contact
.
friends
)
xml
=
@contact
.
to_xml
include: :friends
,
indent:
0
assert_match
%r{<friends type="array">}
,
xml
assert_match
%r{<friend type="Contact">}
,
xml
end
test
"multiple includes"
do
xml
=
@contact
.
to_xml
indent:
0
,
skip_instruct:
true
,
include:
[
:address
,
:friends
]
assert
xml
.
include?
(
@contact
.
address
.
to_xml
(
indent:
0
,
skip_instruct:
true
))
assert_match
%r{<friends type="array">}
,
xml
assert_match
%r{<friend type="Contact">}
,
xml
end
test
"include with options"
do
xml
=
@contact
.
to_xml
indent:
0
,
skip_instruct:
true
,
include:
{
address:
{
only: :city
}
}
assert
xml
.
include?
(
%(><address><city>Springfield</city></address>)
)
end
test
"propagates skip_types option to included associations"
do
xml
=
@contact
.
to_xml
include: :friends
,
indent:
0
,
skip_types:
true
assert_match
%r{<friends>}
,
xml
assert_match
%r{<friend>}
,
xml
end
test
"propagates skip-types option to included associations and attributes"
do
xml
=
@contact
.
to_xml
skip_types:
true
,
include: :address
,
indent:
0
assert_match
%r{<address>}
,
xml
assert_match
%r{<apt-number>}
,
xml
end
test
"propagates camelize option to included associations and attributes"
do
xml
=
@contact
.
to_xml
camelize:
true
,
include: :address
,
indent:
0
assert_match
%r{<Address>}
,
xml
assert_match
%r{<AptNumber type="integer">}
,
xml
end
test
"propagates dasherize option to included associations and attributes"
do
xml
=
@contact
.
to_xml
dasherize:
false
,
include: :address
,
indent:
0
assert_match
%r{<apt_number type="integer">}
,
xml
end
test
"don't propagate skip_types if skip_types is defined at the included association level"
do
xml
=
@contact
.
to_xml
skip_types:
true
,
include:
{
address:
{
skip_types:
false
}
},
indent:
0
assert_match
%r{<address>}
,
xml
assert_match
%r{<apt-number type="integer">}
,
xml
end
test
"don't propagate camelize if camelize is defined at the included association level"
do
xml
=
@contact
.
to_xml
camelize:
true
,
include:
{
address:
{
camelize:
false
}
},
indent:
0
assert_match
%r{<address>}
,
xml
assert_match
%r{<apt-number type="integer">}
,
xml
end
test
"don't propagate dasherize if dasherize is defined at the included association level"
do
xml
=
@contact
.
to_xml
dasherize:
false
,
include:
{
address:
{
dasherize:
true
}
},
indent:
0
assert_match
%r{<address>}
,
xml
assert_match
%r{<apt-number type="integer">}
,
xml
end
test
"association with sti"
do
xml
=
@contact
.
to_xml
(
include: :contact
)
assert
xml
.
include?
(
%(<contact type="SerializableContact">)
)
end
end
activemodel/test/models/contact.rb
浏览文件 @
9645820b
...
...
@@ -4,7 +4,6 @@ class Contact
include
ActiveModel
::
Validations
include
ActiveModel
::
Serializers
::
JSON
include
ActiveModel
::
Serializers
::
Xml
attr_accessor
:id
,
:name
,
:age
,
:created_at
,
:awesome
,
:preferences
attr_accessor
:address
,
:friends
,
:contact
...
...
activerecord/CHANGELOG.md
浏览文件 @
9645820b
...
...
@@ -345,6 +345,10 @@
*Ryuta Kamizono*
*
Remove
`ActiveRecord::Serialization::XmlSerializer`
from core.
*Zachary Scott*
*
Make
`unscope`
aware of "less than" and "greater than" conditions.
*TAKAHASHI Kazuaki*
...
...
activerecord/lib/active_record/serialization.rb
浏览文件 @
9645820b
...
...
@@ -18,5 +18,3 @@ def serializable_hash(options = nil)
end
end
end
require
'active_record/serializers/xml_serializer'
activerecord/lib/active_record/serializers/xml_serializer.rb
已删除
100644 → 0
浏览文件 @
752432e8
require
'active_support/core_ext/hash/conversions'
module
ActiveRecord
#:nodoc:
module
Serialization
include
ActiveModel
::
Serializers
::
Xml
# Builds an XML document to represent the model. Some configuration is
# available through +options+. However more complicated cases should
# override ActiveRecord::Base#to_xml.
#
# By default the generated XML document will include the processing
# instruction and all the object's attributes. For example:
#
# <?xml version="1.0" encoding="UTF-8"?>
# <topic>
# <title>The First Topic</title>
# <author-name>David</author-name>
# <id type="integer">1</id>
# <approved type="boolean">false</approved>
# <replies-count type="integer">0</replies-count>
# <bonus-time type="dateTime">2000-01-01T08:28:00+12:00</bonus-time>
# <written-on type="dateTime">2003-07-16T09:28:00+1200</written-on>
# <content>Have a nice day</content>
# <author-email-address>david@loudthinking.com</author-email-address>
# <parent-id></parent-id>
# <last-read type="date">2004-04-15</last-read>
# </topic>
#
# This behavior can be controlled with <tt>:only</tt>, <tt>:except</tt>,
# <tt>:skip_instruct</tt>, <tt>:skip_types</tt>, <tt>:dasherize</tt> and <tt>:camelize</tt> .
# The <tt>:only</tt> and <tt>:except</tt> options are the same as for the
# +attributes+ method. The default is to dasherize all column names, but you
# can disable this setting <tt>:dasherize</tt> to +false+. Setting <tt>:camelize</tt>
# to +true+ will camelize all column names - this also overrides <tt>:dasherize</tt>.
# To not have the column type included in the XML output set <tt>:skip_types</tt> to +true+.
#
# For instance:
#
# topic.to_xml(skip_instruct: true, except: [ :id, :bonus_time, :written_on, :replies_count ])
#
# <topic>
# <title>The First Topic</title>
# <author-name>David</author-name>
# <approved type="boolean">false</approved>
# <content>Have a nice day</content>
# <author-email-address>david@loudthinking.com</author-email-address>
# <parent-id></parent-id>
# <last-read type="date">2004-04-15</last-read>
# </topic>
#
# To include first level associations use <tt>:include</tt>:
#
# firm.to_xml include: [ :account, :clients ]
#
# <?xml version="1.0" encoding="UTF-8"?>
# <firm>
# <id type="integer">1</id>
# <rating type="integer">1</rating>
# <name>37signals</name>
# <clients type="array">
# <client>
# <rating type="integer">1</rating>
# <name>Summit</name>
# </client>
# <client>
# <rating type="integer">1</rating>
# <name>Microsoft</name>
# </client>
# </clients>
# <account>
# <id type="integer">1</id>
# <credit-limit type="integer">50</credit-limit>
# </account>
# </firm>
#
# Additionally, the record being serialized will be passed to a Proc's second
# parameter. This allows for ad hoc additions to the resultant document that
# incorporate the context of the record being serialized. And by leveraging the
# closure created by a Proc, to_xml can be used to add elements that normally fall
# outside of the scope of the model -- for example, generating and appending URLs
# associated with models.
#
# proc = Proc.new { |options, record| options[:builder].tag!('name-reverse', record.name.reverse) }
# firm.to_xml procs: [ proc ]
#
# <firm>
# # ... normal attributes as shown above ...
# <name-reverse>slangis73</name-reverse>
# </firm>
#
# To include deeper levels of associations pass a hash like this:
#
# firm.to_xml include: {account: {}, clients: {include: :address}}
# <?xml version="1.0" encoding="UTF-8"?>
# <firm>
# <id type="integer">1</id>
# <rating type="integer">1</rating>
# <name>37signals</name>
# <clients type="array">
# <client>
# <rating type="integer">1</rating>
# <name>Summit</name>
# <address>
# ...
# </address>
# </client>
# <client>
# <rating type="integer">1</rating>
# <name>Microsoft</name>
# <address>
# ...
# </address>
# </client>
# </clients>
# <account>
# <id type="integer">1</id>
# <credit-limit type="integer">50</credit-limit>
# </account>
# </firm>
#
# To include any methods on the model being called use <tt>:methods</tt>:
#
# firm.to_xml methods: [ :calculated_earnings, :real_earnings ]
#
# <firm>
# # ... normal attributes as shown above ...
# <calculated-earnings>100000000000000000</calculated-earnings>
# <real-earnings>5</real-earnings>
# </firm>
#
# To call any additional Procs use <tt>:procs</tt>. The Procs are passed a
# modified version of the options hash that was given to +to_xml+:
#
# proc = Proc.new { |options| options[:builder].tag!('abc', 'def') }
# firm.to_xml procs: [ proc ]
#
# <firm>
# # ... normal attributes as shown above ...
# <abc>def</abc>
# </firm>
#
# Alternatively, you can yield the builder object as part of the +to_xml+ call:
#
# firm.to_xml do |xml|
# xml.creator do
# xml.first_name "David"
# xml.last_name "Heinemeier Hansson"
# end
# end
#
# <firm>
# # ... normal attributes as shown above ...
# <creator>
# <first_name>David</first_name>
# <last_name>Heinemeier Hansson</last_name>
# </creator>
# </firm>
#
# As noted above, you may override +to_xml+ in your ActiveRecord::Base
# subclasses to have complete control about what's generated. The general
# form of doing this is:
#
# class IHaveMyOwnXML < ActiveRecord::Base
# def to_xml(options = {})
# require 'builder'
# options[:indent] ||= 2
# xml = options[:builder] ||= ::Builder::XmlMarkup.new(indent: options[:indent])
# xml.instruct! unless options[:skip_instruct]
# xml.level_one do
# xml.tag!(:second_level, 'content')
# end
# end
# end
def
to_xml
(
options
=
{},
&
block
)
XmlSerializer
.
new
(
self
,
options
).
serialize
(
&
block
)
end
end
class
XmlSerializer
<
ActiveModel
::
Serializers
::
Xml
::
Serializer
#:nodoc:
class
Attribute
<
ActiveModel
::
Serializers
::
Xml
::
Serializer
::
Attribute
#:nodoc:
def
compute_type
klass
=
@serializable
.
class
cast_type
=
klass
.
type_for_attribute
(
name
)
type
=
ActiveSupport
::
XmlMini
::
TYPE_NAMES
[
value
.
class
.
name
]
||
cast_type
.
type
{
:text
=>
:string
,
:time
=>
:datetime
}[
type
]
||
type
end
protected
:compute_type
end
end
end
activerecord/test/cases/serialization_test.rb
浏览文件 @
9645820b
...
...
@@ -8,7 +8,7 @@
class
SerializationTest
<
ActiveRecord
::
TestCase
fixtures
:books
FORMATS
=
[
:
xml
,
:
json
]
FORMATS
=
[
:json
]
def
setup
@contact_attributes
=
{
...
...
activerecord/test/cases/xml_serialization_test.rb
已删除
100644 → 0
浏览文件 @
752432e8
require
"cases/helper"
require
"rexml/document"
require
'models/contact'
require
'models/post'
require
'models/author'
require
'models/comment'
require
'models/company_in_module'
require
'models/toy'
require
'models/topic'
require
'models/reply'
require
'models/company'
class
XmlSerializationTest
<
ActiveRecord
::
TestCase
def
test_should_serialize_default_root
@xml
=
Contact
.
new
.
to_xml
assert_match
%r{^<contact>}
,
@xml
assert_match
%r{</contact>$}
,
@xml
end
def
test_should_serialize_default_root_with_namespace
@xml
=
Contact
.
new
.
to_xml
:namespace
=>
"http://xml.rubyonrails.org/contact"
assert_match
%r{^<contact xmlns="http://xml
\.
rubyonrails
\.
org/contact">}
,
@xml
assert_match
%r{</contact>$}
,
@xml
end
def
test_should_serialize_custom_root
@xml
=
Contact
.
new
.
to_xml
:root
=>
'xml_contact'
assert_match
%r{^<xml-contact>}
,
@xml
assert_match
%r{</xml-contact>$}
,
@xml
end
def
test_should_allow_undasherized_tags
@xml
=
Contact
.
new
.
to_xml
:root
=>
'xml_contact'
,
:dasherize
=>
false
assert_match
%r{^<xml_contact>}
,
@xml
assert_match
%r{</xml_contact>$}
,
@xml
assert_match
%r{<created_at}
,
@xml
end
def
test_should_allow_camelized_tags
@xml
=
Contact
.
new
.
to_xml
:root
=>
'xml_contact'
,
:camelize
=>
true
assert_match
%r{^<XmlContact>}
,
@xml
assert_match
%r{</XmlContact>$}
,
@xml
assert_match
%r{<CreatedAt}
,
@xml
end
def
test_should_allow_skipped_types
@xml
=
Contact
.
new
(
:age
=>
25
).
to_xml
:skip_types
=>
true
assert
%r{<age>25</age>}
.
match
(
@xml
)
end
def
test_should_include_yielded_additions
@xml
=
Contact
.
new
.
to_xml
do
|
xml
|
xml
.
creator
"David"
end
assert_match
%r{<creator>David</creator>}
,
@xml
end
def
test_to_xml_with_block
value
=
"Rockin' the block"
xml
=
Contact
.
new
.
to_xml
(
:skip_instruct
=>
true
)
do
|
_xml
|
_xml
.
tag!
"arbitrary-element"
,
value
end
assert_equal
"<contact>"
,
xml
.
first
(
9
)
assert
xml
.
include?
(
%(<arbitrary-element>#{value}</arbitrary-element>)
)
end
def
test_should_skip_instruct_for_included_records
@contact
=
Contact
.
new
@contact
.
alternative
=
Contact
.
new
(
:name
=>
'Copa Cabana'
)
@xml
=
@contact
.
to_xml
(
:include
=>
[
:alternative
])
assert_equal
@xml
.
index
(
'<?xml '
),
0
assert_nil
@xml
.
index
(
'<?xml '
,
1
)
end
end
class
DefaultXmlSerializationTest
<
ActiveRecord
::
TestCase
def
setup
@contact
=
Contact
.
new
(
:name
=>
'aaron stack'
,
:age
=>
25
,
:avatar
=>
'binarydata'
,
:created_at
=>
Time
.
utc
(
2006
,
8
,
1
),
:awesome
=>
false
,
:preferences
=>
{
:gem
=>
'ruby'
}
)
end
def
test_should_serialize_string
assert_match
%r{<name>aaron stack</name>}
,
@contact
.
to_xml
end
def
test_should_serialize_integer
assert_match
%r{<age type="integer">25</age>}
,
@contact
.
to_xml
end
def
test_should_serialize_binary
xml
=
@contact
.
to_xml
assert_match
%r{YmluYXJ5ZGF0YQ==
\n
</avatar>}
,
xml
assert_match
%r{<avatar(.*)(type="binary")}
,
xml
assert_match
%r{<avatar(.*)(encoding="base64")}
,
xml
end
def
test_should_serialize_datetime
assert_match
%r{<created-at type=
\"
dateTime
\"
>2006-08-01T00:00:00Z</created-at>}
,
@contact
.
to_xml
end
def
test_should_serialize_boolean
assert_match
%r{<awesome type=
\"
boolean
\"
>false</awesome>}
,
@contact
.
to_xml
end
def
test_should_serialize_hash
assert_match
%r{<preferences>
\s
*<gem>ruby</gem>
\s
*</preferences>}m
,
@contact
.
to_xml
end
def
test_uses_serializable_hash_with_only_option
def
@contact
.
serializable_hash
(
options
=
nil
)
super
(
only:
%w(name)
)
end
xml
=
@contact
.
to_xml
assert_match
%r{<name>aaron stack</name>}
,
xml
assert_no_match
%r{age}
,
xml
assert_no_match
%r{awesome}
,
xml
end
def
test_uses_serializable_hash_with_except_option
def
@contact
.
serializable_hash
(
options
=
nil
)
super
(
except:
%w(age)
)
end
xml
=
@contact
.
to_xml
assert_match
%r{<name>aaron stack</name>}
,
xml
assert_match
%r{<awesome type=
\"
boolean
\"
>false</awesome>}
,
xml
assert_no_match
%r{age}
,
xml
end
def
test_does_not_include_inheritance_column_from_sti
@contact
=
ContactSti
.
new
(
@contact
.
attributes
)
assert_equal
'ContactSti'
,
@contact
.
type
xml
=
@contact
.
to_xml
assert_match
%r{<name>aaron stack</name>}
,
xml
assert_no_match
%r{<type}
,
xml
assert_no_match
%r{ContactSti}
,
xml
end
def
test_serializable_hash_with_default_except_option_and_excluding_inheritance_column_from_sti
@contact
=
ContactSti
.
new
(
@contact
.
attributes
)
assert_equal
'ContactSti'
,
@contact
.
type
def
@contact
.
serializable_hash
(
options
=
{})
super
({
except:
%w(age)
}.
merge!
(
options
))
end
xml
=
@contact
.
to_xml
assert_match
%r{<name>aaron stack</name>}
,
xml
assert_no_match
%r{age}
,
xml
assert_no_match
%r{<type}
,
xml
assert_no_match
%r{ContactSti}
,
xml
end
end
class
DefaultXmlSerializationTimezoneTest
<
ActiveRecord
::
TestCase
def
test_should_serialize_datetime_with_timezone
with_timezone_config
zone:
"Pacific Time (US & Canada)"
do
toy
=
Toy
.
create
(
:name
=>
'Mickey'
,
:updated_at
=>
Time
.
utc
(
2006
,
8
,
1
))
assert_match
%r{<updated-at type=
\"
dateTime
\"
>2006-07-31T17:00:00-07:00</updated-at>}
,
toy
.
to_xml
end
end
def
test_should_serialize_datetime_with_timezone_reloaded
with_timezone_config
zone:
"Pacific Time (US & Canada)"
do
toy
=
Toy
.
create
(
:name
=>
'Minnie'
,
:updated_at
=>
Time
.
utc
(
2006
,
8
,
1
)).
reload
assert_match
%r{<updated-at type=
\"
dateTime
\"
>2006-07-31T17:00:00-07:00</updated-at>}
,
toy
.
to_xml
end
end
end
class
NilXmlSerializationTest
<
ActiveRecord
::
TestCase
def
setup
@xml
=
Contact
.
new
.
to_xml
(
:root
=>
'xml_contact'
)
end
def
test_should_serialize_string
assert_match
%r{<name nil="true"/>}
,
@xml
end
def
test_should_serialize_integer
assert
%r{<age (.*)/>}
.
match
(
@xml
)
attributes
=
$1
assert_match
%r{nil="true"}
,
attributes
assert_match
%r{type="integer"}
,
attributes
end
def
test_should_serialize_binary
assert
%r{<avatar (.*)/>}
.
match
(
@xml
)
attributes
=
$1
assert_match
%r{type="binary"}
,
attributes
assert_match
%r{encoding="base64"}
,
attributes
assert_match
%r{nil="true"}
,
attributes
end
def
test_should_serialize_datetime
assert
%r{<created-at (.*)/>}
.
match
(
@xml
)
attributes
=
$1
assert_match
%r{nil="true"}
,
attributes
assert_match
%r{type="dateTime"}
,
attributes
end
def
test_should_serialize_boolean
assert
%r{<awesome (.*)/>}
.
match
(
@xml
)
attributes
=
$1
assert_match
%r{type="boolean"}
,
attributes
assert_match
%r{nil="true"}
,
attributes
end
def
test_should_serialize_yaml
assert_match
%r{<preferences nil=
\"
true
\"
/>}
,
@xml
end
end
class
DatabaseConnectedXmlSerializationTest
<
ActiveRecord
::
TestCase
fixtures
:topics
,
:companies
,
:accounts
,
:authors
,
:posts
,
:projects
def
test_to_xml
xml
=
REXML
::
Document
.
new
(
topics
(
:first
).
to_xml
(
:indent
=>
0
))
bonus_time_in_current_timezone
=
topics
(
:first
).
bonus_time
.
xmlschema
written_on_in_current_timezone
=
topics
(
:first
).
written_on
.
xmlschema
assert_equal
"topic"
,
xml
.
root
.
name
assert_equal
"The First Topic"
,
xml
.
elements
[
"//title"
].
text
assert_equal
"David"
,
xml
.
elements
[
"//author-name"
].
text
assert_match
"Have a nice day"
,
xml
.
elements
[
"//content"
].
text
assert_equal
"1"
,
xml
.
elements
[
"//id"
].
text
assert_equal
"integer"
,
xml
.
elements
[
"//id"
].
attributes
[
'type'
]
assert_equal
"1"
,
xml
.
elements
[
"//replies-count"
].
text
assert_equal
"integer"
,
xml
.
elements
[
"//replies-count"
].
attributes
[
'type'
]
assert_equal
written_on_in_current_timezone
,
xml
.
elements
[
"//written-on"
].
text
assert_equal
"dateTime"
,
xml
.
elements
[
"//written-on"
].
attributes
[
'type'
]
assert_equal
"david@loudthinking.com"
,
xml
.
elements
[
"//author-email-address"
].
text
assert_equal
nil
,
xml
.
elements
[
"//parent-id"
].
text
assert_equal
"integer"
,
xml
.
elements
[
"//parent-id"
].
attributes
[
'type'
]
assert_equal
"true"
,
xml
.
elements
[
"//parent-id"
].
attributes
[
'nil'
]
# Oracle enhanced adapter allows to define Date attributes in model class (see topic.rb)
assert_equal
"2004-04-15"
,
xml
.
elements
[
"//last-read"
].
text
assert_equal
"date"
,
xml
.
elements
[
"//last-read"
].
attributes
[
'type'
]
# Oracle and DB2 don't have true boolean or time-only fields
unless
current_adapter?
(
:OracleAdapter
,
:DB2Adapter
)
assert_equal
"false"
,
xml
.
elements
[
"//approved"
].
text
assert_equal
"boolean"
,
xml
.
elements
[
"//approved"
].
attributes
[
'type'
]
assert_equal
bonus_time_in_current_timezone
,
xml
.
elements
[
"//bonus-time"
].
text
assert_equal
"dateTime"
,
xml
.
elements
[
"//bonus-time"
].
attributes
[
'type'
]
end
end
def
test_except_option
xml
=
topics
(
:first
).
to_xml
(
:indent
=>
0
,
:skip_instruct
=>
true
,
:except
=>
[
:title
,
:replies_count
])
assert_equal
"<topic>"
,
xml
.
first
(
7
)
assert
!
xml
.
include?
(
%(<title>The First Topic</title>)
)
assert
xml
.
include?
(
%(<author-name>David</author-name>)
)
xml
=
topics
(
:first
).
to_xml
(
:indent
=>
0
,
:skip_instruct
=>
true
,
:except
=>
[
:title
,
:author_name
,
:replies_count
])
assert
!
xml
.
include?
(
%(<title>The First Topic</title>)
)
assert
!
xml
.
include?
(
%(<author-name>David</author-name>)
)
end
# to_xml used to mess with the hash the user provided which
# caused the builder to be reused. This meant the document kept
# getting appended to.
def
test_modules
projects
=
MyApplication
::
Business
::
Project
.
all
xml
=
projects
.
to_xml
root
=
projects
.
first
.
class
.
to_s
.
underscore
.
pluralize
.
tr
(
'/'
,
'_'
).
dasherize
assert_match
"<
#{
root
}
type=
\"
array
\"
>"
,
xml
assert_match
"</
#{
root
}
>"
,
xml
end
def
test_passing_hash_shouldnt_reuse_builder
options
=
{
:include
=>
:posts
}
david
=
authors
(
:david
)
first_xml_size
=
david
.
to_xml
(
options
).
size
second_xml_size
=
david
.
to_xml
(
options
).
size
assert_equal
first_xml_size
,
second_xml_size
end
def
test_include_uses_association_name
xml
=
authors
(
:david
).
to_xml
:include
=>
:hello_posts
,
:indent
=>
0
assert_match
%r{<hello-posts type="array">}
,
xml
assert_match
%r{<hello-post type="Post">}
,
xml
assert_match
%r{<hello-post type="StiPost">}
,
xml
end
def
test_included_associations_should_skip_types
xml
=
authors
(
:david
).
to_xml
:include
=>
:hello_posts
,
:indent
=>
0
,
:skip_types
=>
true
assert_match
%r{<hello-posts>}
,
xml
assert_match
%r{<hello-post>}
,
xml
assert_match
%r{<hello-post>}
,
xml
end
def
test_including_has_many_association
xml
=
topics
(
:first
).
to_xml
(
:indent
=>
0
,
:skip_instruct
=>
true
,
:include
=>
:replies
,
:except
=>
:replies_count
)
assert_equal
"<topic>"
,
xml
.
first
(
7
)
assert
xml
.
include?
(
%(<replies type="array"><reply>)
)
assert
xml
.
include?
(
%(<title>The Second Topic of the day</title>)
)
end
def
test_including_belongs_to_association
xml
=
companies
(
:first_client
).
to_xml
(
:indent
=>
0
,
:skip_instruct
=>
true
,
:include
=>
:firm
)
assert
!
xml
.
include?
(
"<firm>"
)
xml
=
companies
(
:second_client
).
to_xml
(
:indent
=>
0
,
:skip_instruct
=>
true
,
:include
=>
:firm
)
assert
xml
.
include?
(
"<firm>"
)
end
def
test_including_multiple_associations
xml
=
companies
(
:first_firm
).
to_xml
(
:indent
=>
0
,
:skip_instruct
=>
true
,
:include
=>
[
:clients
,
:account
])
assert_equal
"<firm>"
,
xml
.
first
(
6
)
assert
xml
.
include?
(
%(<account>)
)
assert
xml
.
include?
(
%(<clients type="array"><client>)
)
end
def
test_including_association_with_options
xml
=
companies
(
:first_firm
).
to_xml
(
:indent
=>
0
,
:skip_instruct
=>
true
,
:include
=>
{
:clients
=>
{
:only
=>
:name
}
}
)
assert_equal
"<firm>"
,
xml
.
first
(
6
)
assert
xml
.
include?
(
%(<client><name>Summit</name></client>)
)
assert
xml
.
include?
(
%(<clients type="array"><client>)
)
end
def
test_methods_are_called_on_object
xml
=
authors
(
:david
).
to_xml
:methods
=>
:label
,
:indent
=>
0
assert_match
%r{<label>.*</label>}
,
xml
end
def
test_should_not_call_methods_on_associations_that_dont_respond
xml
=
authors
(
:david
).
to_xml
:include
=>
:hello_posts
,
:methods
=>
:label
,
:indent
=>
2
assert
!
authors
(
:david
).
hello_posts
.
first
.
respond_to?
(
:label
)
assert_match
%r{^ <label>.*</label>}
,
xml
assert_no_match
%r{^ <label>}
,
xml
end
def
test_procs_are_called_on_object
proc
=
Proc
.
new
{
|
options
|
options
[
:builder
].
tag!
(
'nationality'
,
'Danish'
)
}
xml
=
authors
(
:david
).
to_xml
(
:procs
=>
[
proc
])
assert_match
%r{<nationality>Danish</nationality>}
,
xml
end
def
test_dual_arity_procs_are_called_on_object
proc
=
Proc
.
new
{
|
options
,
record
|
options
[
:builder
].
tag!
(
'name-reverse'
,
record
.
name
.
reverse
)
}
xml
=
authors
(
:david
).
to_xml
(
:procs
=>
[
proc
])
assert_match
%r{<name-reverse>divaD</name-reverse>}
,
xml
end
def
test_top_level_procs_arent_applied_to_associations
author_proc
=
Proc
.
new
{
|
options
|
options
[
:builder
].
tag!
(
'nationality'
,
'Danish'
)
}
xml
=
authors
(
:david
).
to_xml
(
:procs
=>
[
author_proc
],
:include
=>
:posts
,
:indent
=>
2
)
assert_match
%r{^ <nationality>Danish</nationality>}
,
xml
assert_no_match
%r{^ {6}<nationality>Danish</nationality>}
,
xml
end
def
test_procs_on_included_associations_are_called
posts_proc
=
Proc
.
new
{
|
options
|
options
[
:builder
].
tag!
(
'copyright'
,
'DHH'
)
}
xml
=
authors
(
:david
).
to_xml
(
:indent
=>
2
,
:include
=>
{
:posts
=>
{
:procs
=>
[
posts_proc
]
}
}
)
assert_no_match
%r{^ <copyright>DHH</copyright>}
,
xml
assert_match
%r{^ {6}<copyright>DHH</copyright>}
,
xml
end
def
test_should_include_empty_has_many_as_empty_array
authors
(
:david
).
posts
.
delete_all
xml
=
authors
(
:david
).
to_xml
:include
=>
:posts
,
:indent
=>
2
assert_equal
[],
Hash
.
from_xml
(
xml
)[
'author'
][
'posts'
]
assert_match
%r{^ <posts type="array"/>}
,
xml
end
def
test_should_has_many_array_elements_should_include_type_when_different_from_guessed_value
xml
=
authors
(
:david
).
to_xml
:include
=>
:posts_with_comments
,
:indent
=>
2
assert
Hash
.
from_xml
(
xml
)
assert_match
%r{^ <posts-with-comments type="array">}
,
xml
assert_match
%r{^ <posts-with-comment type="Post">}
,
xml
assert_match
%r{^ <posts-with-comment type="StiPost">}
,
xml
types
=
Hash
.
from_xml
(
xml
)[
'author'
][
'posts_with_comments'
].
collect
{
|
t
|
t
[
'type'
]
}
assert
types
.
include?
(
'SpecialPost'
)
assert
types
.
include?
(
'Post'
)
assert
types
.
include?
(
'StiPost'
)
end
def
test_should_produce_xml_for_methods_returning_array
xml
=
authors
(
:david
).
to_xml
(
:methods
=>
:social
)
array
=
Hash
.
from_xml
(
xml
)[
'author'
][
'social'
]
assert_equal
2
,
array
.
size
assert
array
.
include?
'twitter'
assert
array
.
include?
'github'
end
def
test_should_support_aliased_attributes
xml
=
Author
.
select
(
"name as firstname"
).
to_xml
Author
.
all
.
each
do
|
author
|
assert
xml
.
include?
(
%(<firstname>#{author.name}</firstname>)
),
xml
end
end
def
test_array_to_xml_including_has_many_association
xml
=
[
topics
(
:first
),
topics
(
:second
)
].
to_xml
(
:indent
=>
0
,
:skip_instruct
=>
true
,
:include
=>
:replies
)
assert
xml
.
include?
(
%(<replies type="array"><reply>)
)
end
def
test_array_to_xml_including_methods
xml
=
[
topics
(
:first
),
topics
(
:second
)
].
to_xml
(
:indent
=>
0
,
:skip_instruct
=>
true
,
:methods
=>
[
:topic_id
])
assert
xml
.
include?
(
%(<topic-id type="integer">#{topics(:first).topic_id}</topic-id>)
),
xml
assert
xml
.
include?
(
%(<topic-id type="integer">#{topics(:second).topic_id}</topic-id>)
),
xml
end
def
test_array_to_xml_including_has_one_association
xml
=
[
companies
(
:first_firm
),
companies
(
:rails_core
)
].
to_xml
(
:indent
=>
0
,
:skip_instruct
=>
true
,
:include
=>
:account
)
assert
xml
.
include?
(
companies
(
:first_firm
).
account
.
to_xml
(
:indent
=>
0
,
:skip_instruct
=>
true
))
assert
xml
.
include?
(
companies
(
:rails_core
).
account
.
to_xml
(
:indent
=>
0
,
:skip_instruct
=>
true
))
end
def
test_array_to_xml_including_belongs_to_association
xml
=
[
companies
(
:first_client
),
companies
(
:second_client
),
companies
(
:another_client
)
].
to_xml
(
:indent
=>
0
,
:skip_instruct
=>
true
,
:include
=>
:firm
)
assert
xml
.
include?
(
companies
(
:first_client
).
to_xml
(
:indent
=>
0
,
:skip_instruct
=>
true
))
assert
xml
.
include?
(
companies
(
:second_client
).
firm
.
to_xml
(
:indent
=>
0
,
:skip_instruct
=>
true
))
assert
xml
.
include?
(
companies
(
:another_client
).
firm
.
to_xml
(
:indent
=>
0
,
:skip_instruct
=>
true
))
end
end
guides/source/active_model_basics.md
浏览文件 @
9645820b
...
...
@@ -319,9 +319,8 @@ person.serializable_hash # => {"name"=>"Bob"}
#### ActiveModel::Serializers
Rails provides two serializers
`ActiveModel::Serializers::JSON`
and
`ActiveModel::Serializers::Xml`
. Both of these modules automatically include
the
`ActiveModel::Serialization`
.
Rails provides a
`ActiveModel::Serializers::JSON`
serializer.
This module automatically include the
`ActiveModel::Serialization`
.
##### ActiveModel::Serializers::JSON
...
...
@@ -379,62 +378,6 @@ person.from_json(json) # => #<Person:0x00000100c773f0 @name="Bob">
person
.
name
# => "Bob"
```
##### ActiveModel::Serializers::Xml
To use the
`ActiveModel::Serializers::Xml`
you only need to change from
`ActiveModel::Serialization`
to
`ActiveModel::Serializers::Xml`
.
```
ruby
class
Person
include
ActiveModel
::
Serializers
::
Xml
attr_accessor
:name
def
attributes
{
'name'
=>
nil
}
end
end
```
With the
`to_xml`
you have an XML representing the model.
```
ruby
person
=
Person
.
new
person
.
to_xml
# => "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<person>\n <name nil=\"true\"/>\n</person>\n"
person
.
name
=
"Bob"
person
.
to_xml
# => "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<person>\n <name>Bob</name>\n</person>\n"
```
From an XML string you define the attributes of the model.
You need to have the
`attributes=`
method defined on your class:
```
ruby
class
Person
include
ActiveModel
::
Serializers
::
Xml
attr_accessor
:name
def
attributes
=
(
hash
)
hash
.
each
do
|
key
,
value
|
send
(
"
#{
key
}
="
,
value
)
end
end
def
attributes
{
'name'
=>
nil
}
end
end
```
Now it is possible to create an instance of person and set the attributes using
`from_xml`
.
```
ruby
xml
=
{
name:
'Bob'
}.
to_xml
person
=
Person
.
new
person
.
from_xml
(
xml
)
# => #<Person:0x00000100c773f0 @name="Bob">
person
.
name
# => "Bob"
```
### Translation
`ActiveModel::Translation`
provides integration between your object and the Rails
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录