将参数散列切片以获得特定值
|
摘要
给定哈希,基于要使用的键列表创建子集哈希的最有效方法是什么?
h1 = { a:1, b:2, c:3 } # Given a hash...
p foo( h1, :a, :c, :d ) # ...create a method that...
#=> { :a=>1, :c=>3, :d=>nil } # ...returns specified keys...
#=> { :a=>1, :c=>3 } # ...or perhaps only keys that exist
细节
Sequel数据库工具箱允许通过传入哈希来创建或更新模型实例:
foo = Product.create( hash_of_column_values )
foo.update( another_hash )
Sinatra Web框架提供了一个名为“ 2”的哈希,其中包括表单变量,查询字符串参数以及路由匹配项。
如果我创建一个仅包含与数据库列名称相同的字段的表单并将其发布到此路由,则一切工作都非常方便:
post \"/create_product\" do
new_product = Product.create params
redirect \"/product/#{new_product.id}\"
end
但是,这既脆弱又危险。这很危险,因为恶意黑客可能会发布一个包含不希望更改的列的表单并进行更新。这很脆弱,因为无法在此路线上使用相同的表格:
post \"/update_product/:foo\" do |prod_id|
if product = Product[prod_id]
product.update(params)
#=> <Sequel::Error: method foo= doesn\'t exist or access is restricted to it>
end
end
因此,出于鲁棒性和安全性,我希望能够编写以下代码:
post \"/update_product/:foo\" do |prod_id|
if product = Product[prod_id]
# Only update two specific fields
product.update(params.slice(:name,:description))
# The above assumes a Hash (or Sinatra params) monkeypatch
# I will also accept standalone helper methods that perform the same
end
end
...而不是更冗长和非DRY的选项:
post \"/update_product/:foo\" do |prod_id|
if product = Product[prod_id]
# Only update two specific fields
product.update({
name:params[:name],
description:params[:description]
})
end
end
更新:基准
这是对(当前)实现进行基准测试的结果:
user system total real
sawa2 0.250000 0.000000 0.250000 ( 0.269027)
phrogz2 0.280000 0.000000 0.280000 ( 0.275027)
sawa1 0.297000 0.000000 0.297000 ( 0.293029)
phrogz3 0.296000 0.000000 0.296000 ( 0.307031)
phrogz1 0.328000 0.000000 0.328000 ( 0.319032)
activesupport 0.639000 0.000000 0.639000 ( 0.657066)
mladen 1.716000 0.000000 1.716000 ( 1.725172)
@sawa的第二个答案是所有答案中最快的,比我基于ѭ8implementation的实现要好(基于他的第一个答案)。选择添加“ 9”支票将花费很少的时间,但仍比ActiveSupport快两倍。
这是基准代码:
h1 = Hash[ (\'a\'..\'z\').zip(1..26) ]
keys = %w[a z c d g A x]
n = 60000
require \'benchmark\'
Benchmark.bmbm do |x|
%w[ sawa2 phrogz2 sawa1 phrogz3 phrogz1 activesupport mladen ].each do |m|
x.report(m){ n.times{ h1.send(m,*keys) } }
end
end
没有找到相关结果
已邀请:
5 个回复
闪票仇门韧
蕾跨立锌煤
当然,请确保更新您的gemfile:
佬棠
如果:name或:description不存在于参数中,那将不会做完全相同的事情。但是假设您希望用户使用您的表单,那不应该成为问题。 我总是可以扩展update_fields以使用带有选项的选项哈希,如果哈希中不存在该选项,该选项将跳过该值。我只是还没有收到要求这样做。
孝铜差
或者,您也可以复制ActiveSupport的
,它看起来更坚固。
babsoft