Permalink
Browse files

Fix to_xml to use #serializable_hash and properly return ObjectIds

  • Loading branch information...
bkeepers committed Apr 18, 2011
1 parent f513ba3 commit 462403555ab1c565afa17bca964bfb202357098f
@@ -27,4 +27,6 @@ def as_json(options=nil)
def to_json(options = nil)
as_json.to_json
end
alias to_str to_s

This comment has been minimized.

Show comment
Hide comment
@jnunemaker

jnunemaker Apr 18, 2011

Contributor

This is so it works with to_xml, correct? We should maybe note this with a comment as it is an odd thing to add.

@jnunemaker

jnunemaker Apr 18, 2011

Contributor

This is so it works with to_xml, correct? We should maybe note this with a comment as it is an odd thing to add.

end
@@ -57,6 +57,10 @@ def serializable_hash(options = nil)
hash
end
def to_xml(options = {}, &block)
XmlSerializer.new(self, options).serialize(&block)
end
private
def serializable_add_includes(options = {})
@@ -91,7 +95,13 @@ def from_xml(xml)
self.new.from_xml(xml)
end
end
end
# Override default Serializer to use #serializable_hash
class XmlSerializer < ::ActiveModel::Serializers::Xml::Serializer
def attributes_hash
@serializable.serializable_hash(options)
end
end
end
end
@@ -0,0 +1,193 @@
require 'test_helper'
class XmlSerializationTest < Test::Unit::TestCase
class Tag
include MongoMapper::EmbeddedDocument
key :name, String
end
class Contact
include MongoMapper::Document
key :name, String
key :age, Integer
key :created_at, Time
key :awesome, Boolean
key :preferences, Hash
many :tags, :class_name => 'XmlSerializationTest::Tag'
end
def setup
Kernel.const_set('TopLevelContact', Doc('TopLevelContact'))
TopLevelContact.key :name, String
Contact.include_root_in_json = false
@contact = Contact.new(
:name => 'Konata Izumi',
:age => 16,
:created_at => Time.utc(2006, 8, 1),
:awesome => true,
:preferences => { :shows => 'anime' }
)
@top_level_contact = TopLevelContact.new(
:name => 'Konata Izumi'
)
end
def teardown
Kernel.send(:remove_const, 'TopLevelContact') if Object.const_defined?('TopLevelContact')
end
should "include root for class with no module" do
assert_match %r{<top-level-contact>}, @top_level_contact.to_xml
end
should "include demodulized root" do
assert_match %r{<contact>}, @contact.to_xml
end
should "encode all encodable attributes" do
xml = @contact.to_xml
assert_no_match %r{_id}, xml
assert_match %r{<id>#{@contact.id}</id>}, xml
assert_match %r{<name>Konata Izumi</name>}, xml
assert_match %r{<age.*>16</age>}, xml
assert_match %r(<created-at type="datetime">), xml
assert_match %r{<awesome type="boolean">true</awesome>}, xml
assert_match %r{<preferences>}, xml
assert_match %r{<shows>anime</shows>}, xml
end
should "allow attribute filtering with only" do
xml = @contact.to_xml(:only => [:name, :age])
assert_no_match %r{<id>}, xml
assert_match %r{<name>Konata Izumi</name>}, xml
assert_match %r{<age type="integer">16</age>}, xml
assert_no_match %r{awesome}, xml
assert_no_match %r{created-at}, xml
assert_no_match %r{preferences}, xml
end
should "allow attribute filtering with except" do
xml = @contact.to_xml(:except => [:name, :age])
assert_no_match %r{<name>Konata Izumi</name>}, xml
assert_no_match %r{<age type="integer">16</age>}, xml
assert_match %r{<id>}, xml
assert_match %r{awesome}, xml
assert_match %r{created-at}, xml
assert_match %r{preferences}, xml
end
context "_id key" do
should "not be included by default" do
assert_no_match %r{_id}, @contact.to_xml
end
should "not be included even if :except is used" do
assert_no_match %r{_id}, @contact.to_xml(:except => :name)
end
end
context "id method" do
setup do
def @contact.label; "Has cheezburger"; end
def @contact.favorite_quote; "Constraints are liberating"; end
end
should "be included by default" do
assert_match %r{<id>#{@contact.id}</id>}, @contact.to_xml
end
should "be included when single method included" do
xml = @contact.to_xml(:methods => :label)
assert_match %r{<id>}, xml
assert_match %r{<label>Has cheezburger</label>}, xml
assert_match %r{<name>Konata Izumi</name>}, xml
assert_no_match %r{favorite_quote}, xml
end
should "be included when multiple methods included" do
xml = @contact.to_xml(:methods => [:label, :favorite_quote])
assert_match %r{<id>}, xml
assert_match %r{<label>Has cheezburger</label>}, xml
assert_match %r{<name>Konata Izumi</name>}, xml
assert_match %r{<favorite-quote>Constraints are liberating</favorite-quote>}, xml
end
should "not be included if :only is present" do
assert_no_match %r{<id}, @contact.to_xml(:only => :name)
end
should "be represented by a string" do
assert_match %r{<id>}, @contact.to_xml
end
end
context "including methods" do
setup do
def @contact.label; "Has cheezburger"; end
def @contact.favorite_quote; "Constraints are liberating"; end
end
should "include single method" do
assert_match %r{<label>Has cheezburger</label>}, @contact.to_xml(:methods => :label)
end
should "include multiple methods" do
xml = @contact.to_xml(:only => :name, :methods => [:label, :favorite_quote])
assert_match %r{<label>Has cheezburger</label>}, xml
assert_match %r{<favorite-quote>Constraints are liberating</favorite-quote>}, xml
assert_match %r{<name>Konata Izumi</name>}, xml
assert_no_match %r{age}, xml
assert_no_match %r{awesome}, xml
assert_no_match %r{created-at}, xml
assert_no_match %r{preferences}, xml
end
end
context "array of records" do
setup do
@contacts = [
Contact.new(:name => 'David', :age => 39),
Contact.new(:name => 'Mary', :age => 14)
]
end
should "allow attribute filtering with only" do
xml = @contacts.to_xml(:only => :name)
assert_match %r{<name>David</name>}, xml
assert_match %r{<name>Mary</name>}, xml
end
should "allow attribute filtering with except" do
xml = @contacts.to_xml(:except => [:name, :preferences, :awesome, :created_at, :updated_at])
assert_match %r{<age type="integer">39</age>}, xml
assert_match %r{<age type="integer">14</age>}, xml
assert_no_match %r{name}, xml
assert_no_match %r{preferences}, xml
assert_no_match %r{awesome}, xml
assert_no_match %r{created-at}, xml
assert_no_match %r{updated-at}, xml
end
end
should "include embedded attributes" do
contact = Contact.new(:name => 'John', :age => 27)
contact.tags = [Tag.new(:name => 'awesome'), Tag.new(:name => 'ruby')]
xml = contact.to_xml
assert_match %r{<tags type="array">}, xml
assert_match %r{<id>#{contact.tags[0].id}</id>}, xml
assert_match %r{<id>#{contact.tags[1].id}</id>}, xml
assert_match %r{<name>awesome</name>}, xml
assert_match %r{<name>ruby</name>}, xml
end
should "include dynamic attributes" do
contact = Contact.new(:name => 'John', :age => 27, :foo => 'bar')
contact['smell'] = 'stinky'
assert_match %r{<smell>stinky</smell>}, contact.to_xml
end
end

2 comments on commit 4624035

@bkeepers

This comment has been minimized.

Show comment
Hide comment
@bkeepers

bkeepers Apr 18, 2011

Contributor

Seriously, ActiveMode'ls to_xml implementation is horrendous. I see a patch to Rails in my near future. :)

Contributor

bkeepers replied Apr 18, 2011

Seriously, ActiveMode'ls to_xml implementation is horrendous. I see a patch to Rails in my near future. :)

@jnunemaker

This comment has been minimized.

Show comment
Hide comment
@jnunemaker

jnunemaker Apr 18, 2011

Contributor

Nice work Brandon!

Contributor

jnunemaker replied Apr 18, 2011

Nice work Brandon!

Please sign in to comment.