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:
parent
cb23816960
commit
187e1f85d0
5 changed files with 65 additions and 13 deletions
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in a new issue