From 846e8587273743b5cc46708b3c0f047bb501fe02 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Fri, 1 Jun 2007 06:48:09 +0000 Subject: Added proper handling of arrays (closes #8537) [hasmanyjosh] git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@6924 5ecf4fe2-1ee6-0310-87b1-e25e094e27de --- activesupport/CHANGELOG | 23 +++++++++++++ .../active_support/core_ext/array/conversions.rb | 2 +- .../active_support/core_ext/hash/conversions.rb | 14 ++++++++ activesupport/test/core_ext/array_ext_test.rb | 4 +-- activesupport/test/core_ext/hash_ext_test.rb | 39 ++++++++++++++++++++-- 5 files changed, 77 insertions(+), 5 deletions(-) (limited to 'activesupport') diff --git a/activesupport/CHANGELOG b/activesupport/CHANGELOG index 15433ca79b..5eb5cf1637 100644 --- a/activesupport/CHANGELOG +++ b/activesupport/CHANGELOG @@ -1,5 +1,28 @@ *SVN* +* Added proper handling of arrays #8537 [hasmanyjosh] + + Before: + Hash.from_xml '' + # => {:images => nil} + + Hash.from_xml 'foo.jpg' + # => {:images => {:image => "foo.jpg"}} + + Hash.from_xml 'foo.jpgbar.jpg' + # => {:images => {:image => ["foo.jpg", "bar.jpg"]}} + + After: + Hash.from_xml '' + # => {:images => []} + + Hash.from_xml 'foo.jpg' + # => {:images => ["foo.jpg"]} + + Hash.from_xml 'foo.jpgbar.jpg' + # => {:images => ["foo.jpg", "bar.jpg"]} + + * Move common DateTime calculations to Date. #8536 [Geoff Buesing] * Added Date#change (like Time#change) [DHH] diff --git a/activesupport/lib/active_support/core_ext/array/conversions.rb b/activesupport/lib/active_support/core_ext/array/conversions.rb index a4d056e81c..6950e21027 100644 --- a/activesupport/lib/active_support/core_ext/array/conversions.rb +++ b/activesupport/lib/active_support/core_ext/array/conversions.rb @@ -63,7 +63,7 @@ module ActiveSupport #:nodoc: opts = options.merge({ :root => children }) - options[:builder].tag!(root) { + options[:builder].tag!(root, options[:skip_types] ? {} : {:type => "array"}) { yield options[:builder] if block_given? each { |e| e.to_xml(opts.merge!({ :skip_instruct => true })) } } diff --git a/activesupport/lib/active_support/core_ext/hash/conversions.rb b/activesupport/lib/active_support/core_ext/hash/conversions.rb index 2334bb671b..2cccd9c30e 100644 --- a/activesupport/lib/active_support/core_ext/hash/conversions.rb +++ b/activesupport/lib/active_support/core_ext/hash/conversions.rb @@ -163,6 +163,20 @@ module ActiveSupport #:nodoc: else content end + elsif value['type'] == 'array' + child_key, entries = value.detect { |k,v| k != 'type' } # child_key is throwaway + if entries.nil? + [] + else + case entries.class.to_s # something weird with classes not matching here. maybe singleton methods breaking is_a? + when "Array" + entries.collect { |v| typecast_xml_value(v) } + when "Hash" + [typecast_xml_value(entries)] + else + raise "can't typecast #{entries.inspect}" + end + end elsif value['type'] == 'string' && value['nil'] != 'true' "" else diff --git a/activesupport/test/core_ext/array_ext_test.rb b/activesupport/test/core_ext/array_ext_test.rb index e5ca4c424f..8c5356ac78 100644 --- a/activesupport/test/core_ext/array_ext_test.rb +++ b/activesupport/test/core_ext/array_ext_test.rb @@ -121,7 +121,7 @@ class ArrayToXmlTests < Test::Unit::TestCase { :name => "Jason", :age => 31, :age_in_millis => BigDecimal.new('1.0') } ].to_xml(:skip_instruct => true, :indent => 0) - assert_equal "", xml.first(17), xml + assert_equal '', xml.first(30) assert xml.include?(%(26)), xml assert xml.include?(%(820497600000)), xml assert xml.include?(%(David)), xml @@ -135,7 +135,7 @@ class ArrayToXmlTests < Test::Unit::TestCase { :name => "David", :age => 26, :age_in_millis => 820497600000 }, { :name => "Jason", :age => 31 } ].to_xml(:skip_instruct => true, :indent => 0, :root => "people") - assert_equal "", xml.first(16) + assert_equal '', xml.first(29) end def test_to_xml_with_options diff --git a/activesupport/test/core_ext/hash_ext_test.rb b/activesupport/test/core_ext/hash_ext_test.rb index a428fe5061..73b873aee8 100644 --- a/activesupport/test/core_ext/hash_ext_test.rb +++ b/activesupport/test/core_ext/hash_ext_test.rb @@ -370,7 +370,7 @@ class HashToXmlTest < Test::Unit::TestCase def test_two_levels_with_array xml = { :name => "David", :addresses => [{ :street => "Paulina" }, { :street => "Evergreen" }] }.to_xml(@xml_options) assert_equal "", xml.first(8) - assert xml.include?(%(
)) + assert xml.include?(%(
)) assert xml.include?(%(
Paulina
)) assert xml.include?(%(
Evergreen
)) assert xml.include?(%(David)) @@ -378,7 +378,7 @@ class HashToXmlTest < Test::Unit::TestCase def test_three_levels_with_array xml = { :name => "David", :addresses => [{ :streets => [ { :name => "Paulina" }, { :name => "Paulina" } ] } ] }.to_xml(@xml_options) - assert xml.include?(%(
)) + assert xml.include?(%(
)) end def test_single_record_from_xml @@ -516,6 +516,41 @@ class HashToXmlTest < Test::Unit::TestCase assert_equal expected_topic_hash, Hash.from_xml(topic_xml)["rsp"]["photos"]["photo"] end + + def test_empty_array_from_xml + blog_xml = <<-XML + + + + XML + expected_blog_hash = {"blog" => {"posts" => []}} + assert_equal expected_blog_hash, Hash.from_xml(blog_xml) + end + + def test_array_with_one_entry_from_xml + blog_xml = <<-XML + + + a post + + + XML + expected_blog_hash = {"blog" => {"posts" => ["a post"]}} + assert_equal expected_blog_hash, Hash.from_xml(blog_xml) + end + + def test_array_with_multiple_entries_from_xml + blog_xml = <<-XML + + + a post + another post + + + XML + expected_blog_hash = {"blog" => {"posts" => ["a post", "another post"]}} + assert_equal expected_blog_hash, Hash.from_xml(blog_xml) + end def test_xsd_like_types_from_xml bacon_xml = <<-EOT -- cgit v1.2.3