Ruby on Rails | Screencasts | Download | Documentation | Weblog | Community | Source

Changeset 7074

Show
Ignore:
Timestamp:
06/21/07 15:07:15 (1 year ago)
Author:
rick
Message:

Added proper handling of arrays. Closes #8537 [hasmanyjosh]

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/activeresource/lib/active_resource/connection.rb

    r7064 r7074  
    8282 
    8383    def xml_from_response(response) 
    84       if response = from_xml_data(Hash.from_xml(response.body)) 
    85         response.first 
    86       else 
    87         nil 
    88       end 
     84      from_xml_data(Hash.from_xml(response.body)) 
    8985    end 
    9086 
     
    151147      # want for ActiveResource. 
    152148      def from_xml_data(data) 
    153         case data 
    154           when Hash 
    155             if data.keys.size == 1 
    156               case data.values.first 
    157                 when Hash  then [ from_xml_data(data.values.first) ] 
    158                 when Array then from_xml_data(data.values.first) 
    159                 else       data.values.first 
    160               end 
    161             else 
    162               data.each_key { |key| data[key] = from_xml_data(data[key]) } 
    163               data 
    164             end 
    165           when Array then data.collect { |val| from_xml_data(val) } 
    166           else data 
     149        if data.is_a?(Hash) && data.keys.size == 1 
     150          data.values.first 
     151        else 
     152          data 
    167153        end 
    168154      end 
     155       
    169156  end 
    170157end 
  • trunk/activeresource/test/base_test.rb

    r6972 r7074  
    1010    @addy  = { :id => 1, :street => '12345 Street' }.to_xml(:root => 'address') 
    1111    @default_request_headers = { 'Content-Type' => 'application/xml' } 
     12    @rick = { :name => "Rick", :age => 25 }.to_xml(:root => "person") 
     13    @people = [{ :id => 1, :name => 'Matz' }, { :id => 2, :name => 'David' }].to_xml(:root => 'people') 
     14    @people_david = [{ :id => 2, :name => 'David' }].to_xml(:root => 'people') 
     15    @addresses = [{ :id => 1, :street => '12345 Street' }].to_xml(:root => 'addresses') 
    1216     
    1317    ActiveResource::HttpMock.respond_to do |mock| 
     
    1923      mock.delete "/people/2.xml",             {}, nil, 400 
    2024      mock.get    "/people/99.xml",            {}, nil, 404 
    21       mock.post   "/people.xml",               {}, "<person><name>Rick</name><age type='integer'>25</age></person>", 201, 'Location' => '/people/5.xml' 
    22       mock.get    "/people.xml",               {}, "<people>#{@matz}#{@david}</people>" 
    23       mock.get    "/people/1/addresses.xml",   {}, "<addresses>#{@addy}</addresses>" 
     25      mock.post   "/people.xml",               {}, @rick, 201, 'Location' => '/people/5.xml' 
     26      mock.get    "/people.xml",               {}, @people 
     27      mock.get    "/people/1/addresses.xml",   {}, @addresses 
    2428      mock.get    "/people/1/addresses/1.xml", {}, @addy 
    2529      mock.get    "/people/1/addresses/2.xml", {}, nil, 404 
     
    226230 
    227231  def test_find_all_by_from 
    228     ActiveResource::HttpMock.respond_to { |m| m.get "/companies/1/people.xml", {}, "<people>#{@david}</people>"
     232    ActiveResource::HttpMock.respond_to { |m| m.get "/companies/1/people.xml", {}, @people_david
    229233   
    230234    people = Person.find(:all, :from => "/companies/1/people.xml") 
     
    234238 
    235239  def test_find_all_by_from_with_options 
    236     ActiveResource::HttpMock.respond_to { |m| m.get "/companies/1/people.xml", {}, "<people>#{@david}</people>"
     240    ActiveResource::HttpMock.respond_to { |m| m.get "/companies/1/people.xml", {}, @people_david
    237241   
    238242    people = Person.find(:all, :from => "/companies/1/people.xml") 
     
    242246 
    243247  def test_find_all_by_symbol_from 
    244     ActiveResource::HttpMock.respond_to { |m| m.get "/people/managers.xml", {}, "<people>#{@david}</people>"
     248    ActiveResource::HttpMock.respond_to { |m| m.get "/people/managers.xml", {}, @people_david
    245249   
    246250    people = Person.find(:all, :from => :managers) 
  • trunk/activeresource/test/base/custom_methods_test.rb

    r6646 r7074  
    77    @matz  = { :id => 1, :name => 'Matz' }.to_xml(:root => 'person') 
    88    @matz_deep  = { :id => 1, :name => 'Matz', :other => 'other' }.to_xml(:root => 'person') 
     9    @matz_array = [{ :id => 1, :name => 'Matz' }].to_xml(:root => 'people') 
    910    @ryan  = { :name => 'Ryan' }.to_xml(:root => 'person') 
    1011    @addy  = { :id => 1, :street => '12345 Street' }.to_xml(:root => 'address') 
     
    1617      mock.get    "/people/1/shallow.xml", {}, @matz 
    1718      mock.get    "/people/1/deep.xml", {}, @matz_deep 
    18       mock.get    "/people/retrieve.xml?name=Matz", {}, "<people>#{@matz}</people>" 
    19       mock.get    "/people/managers.xml", {}, "<people>#{@matz}</people>" 
     19      mock.get    "/people/retrieve.xml?name=Matz", {}, @matz_array 
     20      mock.get    "/people/managers.xml", {}, @matz_array 
    2021      mock.put    "/people/1/promote.xml?position=Manager", {}, nil, 204 
    2122      mock.put    "/people/promote.xml?name=Matz", {}, nil, 204, {} 
  • trunk/activeresource/test/connection_test.rb

    r6864 r7074  
    116116  def test_get_collection_empty 
    117117    people = @conn.get("/people_empty_elements.xml") 
    118     assert_nil people 
     118    assert_equal [], people 
    119119  end 
    120120 
  • trunk/activesupport/CHANGELOG

    r7019 r7074  
    11*SVN* 
     2 
     3* Added proper handling of arrays #8537 [hasmanyjosh] 
     4 
     5  Before: 
     6    Hash.from_xml '<images></images>' 
     7    # => {:images => nil} 
     8 
     9    Hash.from_xml '<images><image>foo.jpg</image></images>' 
     10    # => {:images => {:image => "foo.jpg"}} 
     11 
     12    Hash.from_xml '<images><image>foo.jpg</image><image>bar.jpg</image></images>' 
     13    # => {:images => {:image => ["foo.jpg", "bar.jpg"]}} 
     14 
     15  After: 
     16    Hash.from_xml '<images type="array"></images>' 
     17    # => {:images => []} 
     18 
     19    Hash.from_xml '<images type="array"><image>foo.jpg</image></images>' 
     20    # => {:images => ["foo.jpg"]} 
     21 
     22    Hash.from_xml '<images type="array"><image>foo.jpg</image><image>bar.jpg</image></images>' 
     23    # => {:images => ["foo.jpg", "bar.jpg"]} 
    224 
    325* Improve Time and Date test coverage.  #8646 [Josh Peek] 
  • trunk/activesupport/lib/active_support/core_ext/array/conversions.rb

    r6946 r7074  
    6464          opts = options.merge({ :root => children }) 
    6565 
    66           options[:builder].tag!(root) { 
    67             yield options[:builder] if block_given? 
    68             each { |e| e.to_xml(opts.merge!({ :skip_instruct => true })) } 
    69           } 
     66          xml = options[:builder] 
     67          if empty? 
     68            xml.tag!(root, options[:skip_types] ? {} : {:type => "array"}) 
     69          else 
     70            xml.tag!(root, options[:skip_types] ? {} : {:type => "array"}) { 
     71              yield xml if block_given? 
     72              each { |e| e.to_xml(opts.merge!({ :skip_instruct => true })) } 
     73            } 
     74          end 
    7075        end 
    7176 
  • trunk/activesupport/lib/active_support/core_ext/hash/conversions.rb

    r6946 r7074  
    164164                      content 
    165165                    end 
     166                  elsif value['type'] == 'array' 
     167                    child_key, entries = value.detect { |k,v| k != 'type' }   # child_key is throwaway 
     168                    if entries.nil? 
     169                      [] 
     170                    else 
     171                      case entries.class.to_s   # something weird with classes not matching here.  maybe singleton methods breaking is_a? 
     172                      when "Array" 
     173                        entries.collect { |v| typecast_xml_value(v) } 
     174                      when "Hash" 
     175                        [typecast_xml_value(entries)] 
     176                      else 
     177                        raise "can't typecast #{entries.inspect}" 
     178                      end 
     179                    end 
    166180                  elsif value['type'] == 'string' && value['nil'] != 'true' 
    167181                    "" 
  • trunk/activesupport/test/core_ext/array_ext_test.rb

    r6946 r7074  
    122122    ].to_xml(:skip_instruct => true, :indent => 0) 
    123123 
    124     assert_equal "<records><record>", xml.first(17), xml 
     124    assert_equal '<records type="array"><record>', xml.first(30) 
    125125    assert xml.include?(%(<age type="integer">26</age>)), xml 
    126126    assert xml.include?(%(<age-in-millis type="integer">820497600000</age-in-millis>)), xml 
     
    136136    ].to_xml(:skip_instruct => true, :indent => 0, :root => "people") 
    137137 
    138     assert_equal "<people><person>", xml.first(16
     138    assert_equal '<people type="array"><person>', xml.first(29
    139139  end 
    140140 
  • trunk/activesupport/test/core_ext/hash_ext_test.rb

    r6946 r7074  
    371371    xml = { :name => "David", :addresses => [{ :street => "Paulina" }, { :street => "Evergreen" }] }.to_xml(@xml_options) 
    372372    assert_equal "<person>", xml.first(8) 
    373     assert xml.include?(%(<addresses><address>)) 
     373    assert xml.include?(%(<addresses type="array"><address>)) 
    374374    assert xml.include?(%(<address><street>Paulina</street></address>)) 
    375375    assert xml.include?(%(<address><street>Evergreen</street></address>)) 
     
    379379  def test_three_levels_with_array 
    380380    xml = { :name => "David", :addresses => [{ :streets => [ { :name => "Paulina" }, { :name => "Paulina" } ] } ] }.to_xml(@xml_options) 
    381     assert xml.include?(%(<addresses><address><streets><street><name>)) 
     381    assert xml.include?(%(<addresses type="array"><address><streets type="array"><street><name>)) 
    382382  end 
    383383 
     
    448448  def test_multiple_records_from_xml 
    449449    topics_xml = <<-EOT 
    450       <topics
     450      <topics type="array"
    451451        <topic> 
    452452          <title>The First Topic</title> 
     
    492492    }.stringify_keys 
    493493 
    494     assert_equal expected_topic_hash, Hash.from_xml(topics_xml)["topics"]["topic"].first 
     494    assert_equal expected_topic_hash, Hash.from_xml(topics_xml)["topics"].first 
    495495  end 
    496496 
     
    516516 
    517517    assert_equal expected_topic_hash, Hash.from_xml(topic_xml)["rsp"]["photos"]["photo"] 
     518  end 
     519   
     520  def test_empty_array_from_xml 
     521    blog_xml = <<-XML 
     522      <blog> 
     523        <posts type="array"></posts> 
     524      </blog> 
     525    XML 
     526    expected_blog_hash = {"blog" => {"posts" => []}} 
     527    assert_equal expected_blog_hash, Hash.from_xml(blog_xml) 
     528  end 
     529 
     530  def test_array_with_one_entry_from_xml 
     531    blog_xml = <<-XML 
     532      <blog> 
     533        <posts type="array"> 
     534          <post>a post</post> 
     535        </posts> 
     536      </blog> 
     537    XML 
     538    expected_blog_hash = {"blog" => {"posts" => ["a post"]}} 
     539    assert_equal expected_blog_hash, Hash.from_xml(blog_xml) 
     540  end 
     541 
     542  def test_array_with_multiple_entries_from_xml 
     543    blog_xml = <<-XML 
     544      <blog> 
     545        <posts type="array"> 
     546          <post>a post</post> 
     547          <post>another post</post> 
     548        </posts> 
     549      </blog> 
     550    XML 
     551    expected_blog_hash = {"blog" => {"posts" => ["a post", "another post"]}} 
     552    assert_equal expected_blog_hash, Hash.from_xml(blog_xml) 
    518553  end 
    519554