Code to accompany the weblog posting: Ruby/Rack and Multiple Value Request Param Pain — Part One
Demonstrating multi-value params not working with out-of-the-box Rack, but working with a monkey patched Rack.
Code to accompany the weblog posting: Ruby/Rack and Multiple Value Request Param Pain — Part One
Demonstrating multi-value params not working with out-of-the-box Rack, but working with a monkey patched Rack.
| #!/usr/bin/env ruby | |
| # For an explanation, see my post at http://xampl.com/so/2009/12/16/rubyrack-and-multiple-value-request-param-pain-—-part-one/ | |
| require 'rubygems' | |
| require 'haml' | |
| require 'sinatra' | |
| get '/' do | |
| haml :play, :layout => false | |
| end | |
| post '/' do | |
| puts "#{File.basename(__FILE__)}:#{__LINE__} #{ __method__ } params: #{ params.inspect }" | |
| haml :play, :layout => false | |
| end | |
| use_in_file_templates! | |
| __END__ | |
| @@ play | |
| %html | |
| %head | |
| %title play | |
| %body | |
| %h1 Play | |
| %form{ :method => 'post' } | |
| %select{ :id => 'several', :name => 'several', :size => 4, :multiple => 'multiple' } | |
| %option{ :id => 'one' } one | |
| %option{ :id => 'two' } two | |
| %option{ :id => 'three' } three | |
| %option{ :id => 'four' } four | |
| %input{ :type => 'submit' } |
| #!/usr/bin/env ruby | |
| # For an explanation, see my post at http://xampl.com/so/2009/12/16/rubyrack-and-multiple-value-request-param-pain-—-part-one/ | |
| require 'rubygems' | |
| require 'haml' | |
| require 'sinatra' | |
| require 'rack-monkey-patch' | |
| get '/' do | |
| haml :play, :layout => false | |
| end | |
| post '/' do | |
| puts "#{File.basename(__FILE__)}:#{__LINE__} #{ __method__ } params: #{ params.inspect }" | |
| haml :play, :layout => false | |
| end | |
| use_in_file_templates! | |
| __END__ | |
| @@ play | |
| %html | |
| %head | |
| %title play | |
| %body | |
| %h1 Play | |
| %form{ :method => 'post' } | |
| %select{ :id => 'several', :name => 'several', :size => 4, :multiple => 'multiple' } | |
| %option{ :id => 'one' } one | |
| %option{ :id => 'two' } two | |
| %option{ :id => 'three' } three | |
| %option{ :id => 'four' } four | |
| %input{ :type => 'submit' } |
| # For an explanation, see my post at http://xampl.com/so/2009/12/16/rubyrack-and-multiple-value-request-param-pain-—-part-one/ | |
| require 'rack' | |
| module Rack | |
| module Utils | |
| def normalize_params(params, name, v = nil) | |
| name =~ %r(\A[\[\]]*([^\[\]]+)\]*) | |
| k = $1 || '' | |
| after = $' || '' | |
| return if k.empty? | |
| if after == "" | |
| # The original simply did: params[k] = v | |
| case params[k] | |
| when Array | |
| params[k] << v | |
| when String | |
| params[k] = [ params[k], v ] | |
| else | |
| params[k] = v | |
| end | |
| elsif after == "[]" | |
| params[k] ||= [] | |
| raise TypeError, "expected Array (got #{params[k].class.name}) for param `#{k}'" unless params[k].is_a?(Array) | |
| params[k] << v | |
| elsif after =~ %r(^\[\]\[([^\[\]]+)\]$) || after =~ %r(^\[\](.+)$) | |
| child_key = $1 | |
| params[k] ||= [] | |
| raise TypeError, "expected Array (got #{params[k].class.name}) for param `#{k}'" unless params[k].is_a?(Array) | |
| if params[k].last.is_a?(Hash) && !params[k].last.key?(child_key) | |
| normalize_params(params[k].last, child_key, v) | |
| else | |
| params[k] << normalize_params({}, child_key, v) | |
| end | |
| else | |
| params[k] ||= {} | |
| raise TypeError, "expected Hash (got #{params[k].class.name}) for param `#{k}'" unless params[k].is_a?(Hash) | |
| params[k] = normalize_params(params[k], after, v) | |
| end | |
| return params | |
| end | |
| module_function :normalize_params | |
| end | |
| end |