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

mes*_*600 6 ruby sinatra

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

{"id" => "123", "id2" => "456"}
Run Code Online (Sandbox Code Playgroud)

现在的命令:

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

params['id'] = '999'
puts params          # => {"id" => "999", "id2" => "456"}
Run Code Online (Sandbox Code Playgroud)

但是当我这样做时:

params[:id] = '888'
puts params
Run Code Online (Sandbox Code Playgroud)

我明白了

{"id" => "999", "id2" => "456", :id => "888"}
Run Code Online (Sandbox Code Playgroud)

在IRB中它工作正常:

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

params[:id]
# => nil

params['id']
# => "1"
Run Code Online (Sandbox Code Playgroud)

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

Phr*_*ogz 12

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

irb(main):001:0> { :a=>1, "a"=>2 }
#=> {:a=>1, "a"=>2}
Run Code Online (Sandbox Code Playgroud)

这明显不同于JavaScript,其中对象的键始终是字符串.

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

这是当前的实现:

def indifferent_hash
  Hash.new {|hash,key| hash[key.to_s] if Symbol === key }
end
Run Code Online (Sandbox Code Playgroud)

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