Я передумал. Предыдущий не кажется хорошим.

е

Учитывая хэш, каков наиболее эффективный способ создания подмножества хэша на основе списка используемых ключей?

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
подробности

продолжение Инструментарий базы данных позволяет создать или обновить экземпляр модели, передав хэш:

foo = Product.create( hash_of_column_values )
foo.update( another_hash )

Sinatra веб-фреймворк делает доступным хэш с именемparams это включает переменные формы, параметры строки запроса, а также сопоставления маршрутов.

Если я создаю форму, содержащую только поля, названные так же, как столбцы базы данных, и размещаю ее по этому маршруту, все работает очень удобно:

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

... вместо более многословного и неСУХОГО варианта:

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 самый быстрый из всех, волосы перед моим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

Ответы на вопрос(1)

Ваш ответ на вопрос