使用符号读取和编写Sinatra params,例如PARAMS [:ID]

时间:2012-04-30 21:24:11

标签: ruby sinatra

我的表单通过POST接收数据。当我puts params时,我可以看到:

{"id" => "123", "id2" => "456"}

现在命令:

puts params['id']    # =>  123
puts params[:id]     # =>  123

params['id'] = '999'
puts params          # => {"id" => "999", "id2" => "456"}

但是当我这样做时:

params[:id] = '888'
puts params

我得到了

{"id" => "999", "id2" => "456", :id => "888"}

在IRB中它运作良好:

params
# => {"id2"=>"2", "id"=>"1"}

params[:id]
# => nil

params['id']
# => "1"

为什么我可以使用:id读取值,但不能使用该值设置值?

1 个答案:

答案 0 :(得分:12)

Ruby中的哈希允许将任意对象用作键。由于字符串(例如"id")和符号(例如:id)是不同类型的对象,因此散列可以将具有相同视觉内容的字符串和符号作为键而不会发生冲突:

irb(main):001:0> { :a=>1, "a"=>2 }
#=> {:a=>1, "a"=>2}

这与JavaScript明显不同,JavaScript中对象的键始终是字符串。

由于Web参数(无论是通过GET还是POST)始终是字符串,因此Sinatra具有“便利性”,允许您使用符号请求参数,并在查找关联值之前将其转换为字符串。它通过使用在查找不存在的值时调用to_s的自定义default_proc来实现此目的。

这是current implementation

def indifferent_hash
  Hash.new {|hash,key| hash[key.to_s] if Symbol === key }
end

但是,它没有为[]=(key, val)方法提供自定义实现,因此您可以设置符号而不是字符串。