Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reading and writing Sinatra params using symbols, e.g. params[:id]

Tags:

ruby

sinatra

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?

like image 550
meso_2600 Avatar asked Apr 30 '12 21:04

meso_2600


People also ask

What is params in Sinatra?

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 .

What is params ID?

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.


1 Answers

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.

like image 196
Phrogz Avatar answered Nov 15 '22 12:11

Phrogz