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

Changeset 7834

Show
Ignore:
Timestamp:
10/11/07 05:56:58 (2 years ago)
Author:
bitsweat
Message:

Backport: allow array and hash query parameters. Array route parameters are converted/to/a/path as before. Closes #7047.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • branches/1-2-stable/actionpack/CHANGELOG

    r7783 r7834  
    11*SVN* 
     2 
     3* Backport: allow array and hash query parameters. Array route parameters are converted/to/a/path as before.  #6765, #7047, #7462 [bgipsy, Jeremy McAnally, Dan Kubb, brendan, Diego Algorta Casamayou] 
    24 
    35* Fix in place editor's setter action with non-string fields.  #7418 [Andreas] 
  • branches/1-2-stable/actionpack/lib/action_controller/routing.rb

    r7713 r7834  
    452452      # the query string. The query string will correctly build array parameter 
    453453      # values. 
    454       def build_query_string(hash, only_keys=nil) 
     454      def build_query_string(hash, only_keys = nil) 
    455455        elements = [] 
    456  
    457         only_keys ||= hash.keys 
    458456         
    459         only_keys.each do |key| 
    460           value = hash[key] or next 
    461           key = CGI.escape key.to_s 
    462           if value.class == Array 
    463             key <<  '[]' 
    464           else     
    465             value = [ value ]  
    466           end      
    467           value.each { |val| elements << "#{key}=#{CGI.escape(val.to_param.to_s)}" } 
    468         end      
    469          
    470         query_string = "?#{elements.join("&")}" unless elements.empty? 
    471         query_string || "" 
    472       end 
    473    
     457        (only_keys || hash.keys).each do |key| 
     458          if value = hash[key] 
     459            elements << value.to_query(key) 
     460          end 
     461        end 
     462        elements.empty? ? '' : "?#{elements.sort * '&'}" 
     463      end 
     464 
    474465      # Write the real recognition implementation and then resend the message. 
    475466      def recognize(path, environment={}) 
     
    669660   
    670661      def extract_value 
    671         "#{local_name} = hash[:#{key}] #{"|| #{default.inspect}" if default}" 
     662        "#{local_name} = hash[:#{key}] && hash[:#{key}].to_param #{"|| #{default.inspect}" if default}" 
    672663      end 
    673664      def value_check 
     
    12311222        # great fun, eh? 
    12321223 
    1233         options_as_params = options[:controller] ? { :action => "index" } : {} 
    1234         options.each do |k, value| 
    1235           options_as_params[k] = value.to_param 
    1236         end 
     1224        options_as_params = options.clone 
     1225        options_as_params[:action] ||= 'index' if options[:controller] 
     1226        options_as_params[:action] = options_as_params[:action].to_s if options_as_params[:action] 
    12371227        options_as_params 
    12381228      end 
  • branches/1-2-stable/actionpack/test/controller/routing_test.rb

    r6677 r7834  
    947947 
    948948  def test_expand_array_build_query_string 
    949     assert_equal '?x[]=1&x[]=2', order_query_string(@route.build_query_string(:x => [1, 2])) 
     949    assert_equal '?x%5B%5D=1&x%5B%5D=2', order_query_string(@route.build_query_string(:x => [1, 2])) 
    950950  end 
    951951 
  • branches/1-2-stable/actionpack/test/controller/url_rewriter_test.rb

    r6651 r7834  
    2424    ) 
    2525  end 
    26    
    27   private 
    28     def split_query_string(str) 
    29       [str[0].chr] + str[1..-1].split(/&/).sort 
    30     end 
    31    
    32     def assert_query_equal(q1, q2) 
    33       assert_equal(split_query_string(q1), split_query_string(q2)) 
    34     end 
    3526end 
    3627 
     
    124115    ActionController::Routing::Routes.load! 
    125116  end 
    126    
     117 
     118  def test_one_parameter 
     119    assert_equal('/c/a?param=val', 
     120      W.new.url_for(:only_path => true, :controller => 'c', :action => 'a', :param => 'val') 
     121    ) 
     122  end 
     123 
     124  def test_two_parameters 
     125    url = W.new.url_for(:only_path => true, :controller => 'c', :action => 'a', :p1 => 'X1', :p2 => 'Y2') 
     126    params = extract_params(url) 
     127    assert_equal params[0], { :p1 => 'X1' }.to_query 
     128    assert_equal params[1], { :p2 => 'Y2' }.to_query 
     129  end 
     130 
     131  def test_hash_parameter 
     132    url = W.new.url_for(:only_path => true, :controller => 'c', :action => 'a', :query => {:name => 'Bob', :category => 'prof'}) 
     133    params = extract_params(url) 
     134    assert_equal params[0], { 'query[category]' => 'prof' }.to_query 
     135    assert_equal params[1], { 'query[name]'     => 'Bob'  }.to_query 
     136  end 
     137 
     138  def test_array_parameter 
     139    url = W.new.url_for(:only_path => true, :controller => 'c', :action => 'a', :query => ['Bob', 'prof']) 
     140    params = extract_params(url) 
     141    assert_equal params[0], { 'query[]' => 'Bob'  }.to_query 
     142    assert_equal params[1], { 'query[]' => 'prof' }.to_query 
     143  end 
     144 
     145  def test_hash_recursive_parameters 
     146    url = W.new.url_for(:only_path => true, :controller => 'c', :action => 'a', :query => {:person => {:name => 'Bob', :position => 'prof'}, :hobby => 'piercing'}) 
     147    params = extract_params(url) 
     148    assert_equal params[0], { 'query[hobby]'            => 'piercing' }.to_query 
     149    assert_equal params[1], { 'query[person][name]'     => 'Bob'      }.to_query 
     150    assert_equal params[2], { 'query[person][position]' => 'prof'     }.to_query 
     151  end 
     152 
     153  def test_hash_recursive_and_array_parameters 
     154    url = W.new.url_for(:only_path => true, :controller => 'c', :action => 'a', :id => 101, :query => {:person => {:name => 'Bob', :position => ['prof', 'art director']}, :hobby => 'piercing'}) 
     155    assert_match %r(^/c/a/101), url 
     156    params = extract_params(url) 
     157    assert_equal params[0], { 'query[hobby]'              => 'piercing'     }.to_query 
     158    assert_equal params[1], { 'query[person][name]'       => 'Bob'          }.to_query 
     159    assert_equal params[2], { 'query[person][position][]' => 'art director' }.to_query 
     160    assert_equal params[3], { 'query[person][position][]' => 'prof'         }.to_query 
     161  end 
     162 
     163  private 
     164    def extract_params(url) 
     165      url.split('?', 2).last.split('&') 
     166    end 
    127167end 
  • branches/1-2-stable/activesupport/CHANGELOG

    r7740 r7834  
     1*SVN* 
     2 
     3* Backport: allow array and hash query parameters. Array route parameters are converted/to/a/path as before.  #6765, #7047, #7462 [bgipsy, Jeremy McAnally, Dan Kubb, brendan, Diego Algorta Casamayou] 
     4 
     5 
    16*1.4.3* (October 4th, 2007) 
    27 
  • branches/1-2-stable/activesupport/lib/active_support/core_ext/hash/conversions.rb

    r7087 r7834  
    11require 'date' 
    22require 'xml_simple' 
     3require 'cgi' 
     4  
     5# Extensions needed for Hash#to_query 
     6class Object 
     7  def to_param #:nodoc: 
     8    to_s 
     9  end 
     10 
     11  def to_query(key) #:nodoc: 
     12    "#{CGI.escape(key.to_s)}=#{CGI.escape(to_param.to_s)}" 
     13  end 
     14end 
     15 
     16class Array 
     17  def to_query(key) #:nodoc: 
     18    collect { |value| value.to_query("#{key}[]") }.sort * '&' 
     19  end 
     20end 
    321 
    422# Locked down XmlSimple#xml_in_string 
     
    4765        def self.included(klass) 
    4866          klass.extend(ClassMethods) 
     67        end 
     68 
     69        def to_query(namespace = nil) 
     70          collect do |key, value| 
     71            value.to_query(namespace ? "#{namespace}[#{key}]" : key) 
     72          end.sort * '&' 
    4973        end 
    5074 
  • branches/1-2-stable/activesupport/test/core_ext/hash_ext_test.rb

    r5522 r7834  
    471471  end 
    472472end 
     473 
     474class QueryTest < Test::Unit::TestCase 
     475  def test_simple_conversion 
     476    assert_query_equal 'a=10', :a => 10 
     477  end 
     478 
     479  def test_cgi_escaping 
     480    assert_query_equal 'a%3Ab=c+d', 'a:b' => 'c d' 
     481  end 
     482 
     483  def test_nil_parameter_value 
     484    empty = Object.new  
     485    def empty.to_param; nil end 
     486    assert_query_equal 'a=', 'a' => empty 
     487  end 
     488 
     489  def test_nested_conversion 
     490    assert_query_equal 'person%5Bname%5D=Nicholas&person%5Blogin%5D=seckar', 
     491      :person => {:name => 'Nicholas', :login => 'seckar'} 
     492  end 
     493   
     494  def test_multiple_nested 
     495    assert_query_equal 'account%5Bperson%5D%5Bid%5D=20&person%5Bid%5D=10', 
     496      :person => {:id => 10}, :account => {:person => {:id => 20}} 
     497  end 
     498   
     499  def test_array_values 
     500    assert_query_equal 'person%5Bid%5D%5B%5D=10&person%5Bid%5D%5B%5D=20', 
     501      :person => {:id => [10, 20]} 
     502  end 
     503 
     504  private 
     505    def assert_query_equal(expected, actual, message = nil) 
     506      assert_equal expected.split('&').sort, actual.to_query.split('&').sort 
     507    end 
     508end 
     509