1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00

to_xml should also rely on serializable hash.

This commit is contained in:
José Valim 2011-09-18 09:09:01 -07:00
parent cb0dbe35b8
commit 51bef9d8fb
3 changed files with 35 additions and 34 deletions

View file

@ -15,10 +15,10 @@ module ActiveModel
class Attribute #:nodoc:
attr_reader :name, :value, :type
def initialize(name, serializable, raw_value=nil)
def initialize(name, serializable, value)
@name, @serializable = name, serializable
raw_value = raw_value.in_time_zone if raw_value.respond_to?(:in_time_zone)
@value = raw_value || @serializable.send(name)
value = value.in_time_zone if value.respond_to?(:in_time_zone)
@value = value
@type = compute_type
end
@ -49,40 +49,24 @@ module ActiveModel
def initialize(serializable, options = nil)
@serializable = serializable
@options = options ? options.dup : {}
@options[:only] = Array.wrap(@options[:only]).map { |n| n.to_s }
@options[:except] = Array.wrap(@options[:except]).map { |n| n.to_s }
end
# To replicate the behavior in ActiveRecord#attributes, <tt>:except</tt>
# takes precedence over <tt>:only</tt>. If <tt>:only</tt> is not set
# for a N level model but is set for the N+1 level models,
# then because <tt>:except</tt> is set to a default value, the second
# level model can have both <tt>:except</tt> and <tt>:only</tt> set. So if
# <tt>:only</tt> is set, always delete <tt>:except</tt>.
def attributes_hash
attributes = @serializable.attributes
if options[:only].any?
attributes.slice(*options[:only])
elsif options[:except].any?
attributes.except(*options[:except])
else
attributes
def serializable_hash
@serializable.serializable_hash(@options.except(:include))
end
def serializable_collection
methods = Array.wrap(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 serializable_attributes
attributes_hash.map do |name, value|
self.class::Attribute.new(name, @serializable, value)
end
end
def serializable_methods
Array.wrap(options[:methods]).map do |name|
self.class::MethodAttribute.new(name.to_s, @serializable) if @serializable.respond_to?(name.to_s)
end.compact
end
def serialize
require 'builder' unless defined? ::Builder
@ -114,7 +98,7 @@ module ActiveModel
end
def add_attributes_and_methods
(serializable_attributes + serializable_methods).each do |attribute|
serializable_collection.each do |attribute|
key = ActiveSupport::XmlMini.rename_key(attribute.name, options)
ActiveSupport::XmlMini.to_tag(key, attribute.value,
options.merge(attribute.decorations))

View file

@ -33,6 +33,12 @@ class Address
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
@ -96,6 +102,17 @@ class XmlSerializationTest < ActiveModel::TestCase
assert_match %r{<createdAt}, @xml
end
test "should use serialiable 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

View file

@ -179,7 +179,7 @@ module ActiveRecord #:nodoc:
class XmlSerializer < ActiveModel::Serializers::Xml::Serializer #:nodoc:
def initialize(*args)
super
options[:except] |= Array.wrap(@serializable.class.inheritance_column)
options[:except] = Array.wrap(options[:except]) | Array.wrap(@serializable.class.inheritance_column)
end
class Attribute < ActiveModel::Serializers::Xml::Serializer::Attribute #:nodoc: