提交 187e1f85 编写于 作者: T Tobias Lütke

Support for non heterogeneous arrays when serializing to xml. Unless guessable...

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
上级 cb238169
......@@ -364,4 +364,11 @@ def test_asset_host_without_protocol_should_use_request_protocol
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 @@ def add_includes
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 @@ def serialize
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 '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 @@ def test_passing_hash_shouldnt_reuse_builder
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 @@ def test_should_include_empty_has_many_as_empty_array
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
\ No newline at end of file
......@@ -167,7 +167,7 @@ def from_xml(xml)
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 @@ def typecast_xml_value(value)
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 @@ def test_xsd_like_types_from_xml
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)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册