6

我的表单通过 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,但不能使用它设置值?

4

1 回答 1

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 来做到这一点。

这是当前的实现

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

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

于 2012-04-30T21:32:16.787 回答