My form receives data via POST. When I do puts params I can see:
{"id" => "123", "id2" => "456"}
now the commands:
puts params['id'] # => 123
puts params[:id] # => 123
params['id'] = '999'
puts params # => {"id" => "999", "id2" => "456"}
but when I do:
params[:id] = '888'
puts params
I get
{"id" => "999", "id2" => "456", :id => "888"}
In IRB it works fine:
params
# => {"id2"=>"2", "id"=>"1"}
params[:id]
# => nil
params['id']
# => "1"
Why can I read the value using :id, but not set the value using that?
Params is short for the word parameter. A parameter is a key-value pair that is encoded in a HTTP request. There are three kinds of params: user supplied parameters , routing parameters , and default parameters .
params[:id] is meant to be the string that uniquely identifies a (RESTful) resource within your Rails application. It is found in the URL after the resource's name.
Hashes in Ruby allow arbitrary objects to be used as keys. As strings (e.g. "id") and symbols (e.g. :id) are separate types of objects, a hash may have as a key both a string and symbol with the same visual contents without conflict:
irb(main):001:0> { :a=>1, "a"=>2 }
#=> {:a=>1, "a"=>2}
This is distinctly different from JavaScript, where the keys for objects are always strings.
Because web parameters (whether via GET or POST) are always strings, Sinatra has a 'convenience' that allows you to ask for a parameter using a symbol and it will convert it to a string before looking for the associated value. It does this by using a custom default_proc that calls to_s when looking for a value that does not exist.
Here's the current implementation:
def indifferent_hash
Hash.new {|hash,key| hash[key.to_s] if Symbol === key }
end
However, it does not provide a custom implementation for the []=(key, val) method, and thus you can set a symbol instead of the string.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With