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

Support for non heterogeneous arrays when serializing to xml. Unless guessable from array name the type name will be included as attribute

git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@7173 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
This commit is contained in:
Tobias Lütke 2007-07-09 22:07:39 +00:00
parent cb23816960
commit 187e1f85d0
5 changed files with 65 additions and 13 deletions

View file

@ -364,4 +364,11 @@ class AssetTagHelperNonVhostTest < Test::Unit::TestCase
ensure
ActionController::Base.asset_host = nil
end
def test_asset_host_without_protocol_should_use_request_protocol_even_if_path_present
ActionController::Base.asset_host = 'a.example.com/files/go/here'
assert_equal 'gopher://a.example.com/files/go/here/collaboration/hieraki/images/xml.png', image_path('xml.png')
ensure
ActionController::Base.asset_host = nil
end
end

View file

@ -211,7 +211,13 @@ module ActiveRecord #:nodoc:
builder.tag!(tag, :type => :array)
else
builder.tag!(tag, :type => :array) do
records.each { |r| r.to_xml(opts.merge(:root=>r.class.to_s.underscore)) }
association_name = association.to_s.singularize
records.each do |record|
record.to_xml opts.merge(
:root => association_name,
:type => (record.class.to_s.underscore == association_name ? nil : record.class.name)
)
end
end
end
when :has_one, :belongs_to
@ -247,6 +253,10 @@ module ActiveRecord #:nodoc:
if options[:namespace]
args << {:xmlns=>options[:namespace]}
end
if options[:type]
args << {:type=>options[:type]}
end
builder.tag!(*args) do
add_attributes

View file

@ -2,6 +2,7 @@ require 'abstract_unit'
require 'fixtures/post'
require 'fixtures/author'
require 'fixtures/tagging'
require 'fixtures/comment'
class Contact < ActiveRecord::Base
# mock out self.columns so no pesky db is needed for these tests
@ -147,8 +148,8 @@ class DatabaseConnectedXmlSerializationTest < Test::Unit::TestCase
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{<post>}, xml
assert_match %r{<sti-post>}, xml
assert_match %r{<hello-post type="Post">}, xml
assert_match %r{<hello-post type="StiPost">}, xml
end
def test_methods_are_called_on_object
@ -171,4 +172,18 @@ class DatabaseConnectedXmlSerializationTest < Test::Unit::TestCase
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
end

View file

@ -167,7 +167,7 @@ module ActiveSupport #:nodoc:
private
def typecast_xml_value(value)
case value.class.to_s
when "Hash"
when 'Hash'
if value.has_key?("__content__")
content = translate_xml_entities(value["__content__"])
if parser = XML_PARSING[value["type"]]
@ -195,31 +195,34 @@ module ActiveSupport #:nodoc:
end
elsif value['type'] == 'string' && value['nil'] != 'true'
""
# blank or nil parsed values are represented by nil
elsif value.blank? || value['nil'] == 'true'
nil
# If the type is the only element which makes it then
# this still makes the value nil
elsif value['type'] && value.size == 1
nil
else
xml_value = (value.blank? || value['type'] || value['nil'] == 'true') ? nil : value.inject({}) do |h,(k,v)|
xml_value = value.inject({}) do |h,(k,v)|
h[k] = typecast_xml_value(v)
h
end
# Turn { :files => { :file => #<StringIO> } into { :files => #<StringIO> } so it is compatible with
# how multipart uploaded files from HTML appear
if xml_value.is_a?(Hash) && xml_value["file"].is_a?(StringIO)
xml_value["file"]
else
xml_value
end
xml_value["file"].is_a?(StringIO) ? xml_value["file"] : xml_value
end
when "Array"
when 'Array'
value.map! { |i| typecast_xml_value(i) }
case value.length
when 0 then nil
when 1 then value.first
else value
end
when "String"
when 'String'
value
else
raise "can't typecast #{value.inspect}"
raise "can't typecast #{value.class.name} - #{value.inspect}"
end
end

View file

@ -588,6 +588,23 @@ class HashToXmlTest < Test::Unit::TestCase
assert_equal expected_bacon_hash, Hash.from_xml(bacon_xml)["bacon"]
end
def test_type_trickles_through_when_unknown
product_xml = <<-EOT
<product>
<weight type="double">0.5</weight>
<image type="ProductImage"><filename>image.gif</filename></image>
</product>
EOT
expected_product_hash = {
:weight => 0.5,
:image => {'type' => 'ProductImage', 'filename' => 'image.gif' },
}.stringify_keys
assert_equal expected_product_hash, Hash.from_xml(product_xml)["product"]
end
def test_should_use_default_value_for_unknown_key
hash_wia = HashWithIndifferentAccess.new(3)