Summary

Given a Hash, what is the most efficient way to create a subset Hash based on a list of keys to use?

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

Details

The Sequel database toolkit allows one to create or update a model instance by passing in a Hash:

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

The Sinatra web framework makes available a Hash named params that includes form variables, querystring parameters and also route matches.

If I create a form holding only fields named the same as the database columns and post it to this route, everything works very conveniently:

post "/create_product" do
  new_product = Product.create params
  redirect "/product/#{new_product.id}"
end

However, this is both fragile and dangerous. It's dangerous because a malicious hacker could post a form with columns not intended to be changed and have them updated. It's fragile because using the same form with this route will not work:

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

So, for robustness and security I want to be able to write this:

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 
Edit
Report