Phr*_*ogz 14 ruby hash sinatra sequel
给定Hash,基于要使用的键列表创建子集Hash的最有效方法是什么?
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
Run Code Online (Sandbox Code Playgroud)
在续集数据库工具包允许一个通过传递一个Hash创建或更新模型实例:
foo = Product.create( hash_of_column_values )
foo.update( another_hash )
Run Code Online (Sandbox Code Playgroud)
该西纳特拉 Web框架使可用命名一个哈希params
包括表单变量,查询字符串参数也路由匹配.
如果我创建一个只包含与数据库列相同的字段的表单并将其发布到此路由,则一切都非常方便:
post "/create_product" do
new_product = Product.create params
redirect "/product/#{new_product.id}"
end
Run Code Online (Sandbox Code Playgroud)
然而,这既脆弱又危险.这是危险的,因为恶意黑客可以发布一个表格,其中的列不打算更改并更新.它很脆弱,因为在这条路线上使用相同的形式是行不通的:
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
Run Code Online (Sandbox Code Playgroud)
因此,为了健壮性和安全性,我希望能够写出:
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
Run Code Online (Sandbox Code Playgroud)
...而不是更详细和非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
Run Code Online (Sandbox Code Playgroud)
以下是对(当前)实现进行基准测试的结果:
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)
Run Code Online (Sandbox Code Playgroud)
@sawa的第二个答案是最快的,在我tap
基于我的实现前面的头发(根据他的第一个答案).选择添加检查has_key?
会增加非常少的时间,并且仍然是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
Run Code Online (Sandbox Code Playgroud)
Bla*_*lor 19
我只想使用active_support提供的切片方法
require 'active_support/core_ext/hash/slice'
{a: 1, b: 2, c: 3}.slice(:a, :c) # => {a: 1, c: 3}
Run Code Online (Sandbox Code Playgroud)
当然,请确保更新您的gemfile:
gem 'active_support'
Run Code Online (Sandbox Code Playgroud)
我改变了主意。上一张好像不太好。
class Hash
def slice1(*keys)
keys.each_with_object({}){|k, h| h[k] = self[k]}
end
def slice2(*keys)
h = {}
keys.each{|k| h[k] = self[k]}
h
end
end
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
7249 次 |
最近记录: |