aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTobias Lütke <tobias.luetke@gmail.com>2007-07-09 22:07:39 +0000
committerTobias Lütke <tobias.luetke@gmail.com>2007-07-09 22:07:39 +0000
commit187e1f85d0c871ba61e5bc3651a7ec2f657db8f9 (patch)
treec260f539da2ec6457aa732f3fb98c7926a80fe9f
parentcb2381696029ad839ecddad08afea061d07685fb (diff)
downloadrails-187e1f85d0c871ba61e5bc3651a7ec2f657db8f9.tar.gz
rails-187e1f85d0c871ba61e5bc3651a7ec2f657db8f9.tar.bz2
rails-187e1f85d0c871ba61e5bc3651a7ec2f657db8f9.zip
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
-rw-r--r--actionpack/test/template/asset_tag_helper_test.rb7
-rw-r--r--activerecord/lib/active_record/xml_serialization.rb12
-rw-r--r--activerecord/test/xml_serialization_test.rb19
-rw-r--r--activesupport/lib/active_support/core_ext/hash/conversions.rb23
-rw-r--r--activesupport/test/core_ext/hash_ext_test.rb17
5 files changed, 65 insertions, 13 deletions
diff --git a/actionpack/test/template/asset_tag_helper_test.rb b/actionpack/test/template/asset_tag_helper_test.rb
index cd4b56a2a0..65b0d368d8 100644
--- a/actionpack/test/template/asset_tag_helper_test.rb
+++ b/actionpack/test/template/asset_tag_helper_test.rb
@@ -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
diff --git a/activerecord/lib/active_record/xml_serialization.rb b/activerecord/lib/active_record/xml_serialization.rb
index 42fe46bca3..7e2d5dd01e 100644
--- a/activerecord/lib/active_record/xml_serialization.rb
+++ b/activerecord/lib/active_record/xml_serialization.rb
@@ -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
diff --git a/activerecord/test/xml_serialization_test.rb b/activerecord/test/xml_serialization_test.rb
index 807daddabb..f6e3d0dd9d 100644
--- a/activerecord/test/xml_serialization_test.rb
+++ b/activerecord/test/xml_serialization_test.rb
@@ -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 \ No newline at end of file
diff --git a/activesupport/lib/active_support/core_ext/hash/conversions.rb b/activesupport/lib/active_support/core_ext/hash/conversions.rb
index 929dd45e98..d8c6852e25 100644
--- a/activesupport/lib/active_support/core_ext/hash/conversions.rb
+++ b/activesupport/lib/active_support/core_ext/hash/conversions.rb
@@ -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
diff --git a/activesupport/test/core_ext/hash_ext_test.rb b/activesupport/test/core_ext/hash_ext_test.rb
index c2b7a7f1eb..17bfb3a92c 100644
--- a/activesupport/test/core_ext/hash_ext_test.rb
+++ b/activesupport/test/core_ext/hash_ext_test.rb
@@ -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)