Q:

How can I dynamically generate parameters for a create method?

I have a model "Item", and I want to generate a bunch of Items with data taken from a CSV file. But I want to allow the user to select which data columns are used.
So my model "User" has a json attribute called Columns, telling which columns should be used from that user's CSV file. For example, if user.columns == {"title"=>"true","category"=>"false"}, then the Title column should be used but the Category column shouldn't.
(Alternatively, I could only list the columns I want to include, like this: {"title"=>"included"}, and later do something like user.columns.each {|c| c[0]} to get an array of all the included columns.)
I have a method for generating Items based on the CSV data:
def create
  #...
  SmarterCSV.process(file).each do |row| #this line returns an array of all the rows in the CSV file
    Item.create(title: row[:title], category: row[:category])
  end
end

but how can I modify the method's parameters based on the contents of user.columns? For the {"title"=>"true","category"=>"false"} example, the method would just be Item.create(name: row[:title]). Is it possible to dynamically generate a method like that?
I'm planning to have quite a lot of possible columns, so doing an if conditional for every possibility is unfeasible.

A:

Item.create(name: row[:name]) also takes a hash, and can be written equivalently as Item.create({ name: row[:name] })
As such - you can build up the entire object in a hash each time; then slice off any attributes that you don't want, and then pass to create. So assuming you have:
user.columns
#=> {"name"=>"true","category"=>"false"}

Then you could write:
user_object = { "name" => row[:name], "category" => row[:category] }
#=> include all the possible attributes here

included_attributes = user.columns.select { |k, v| v == "true" }
#=> {"name"=>"true"}

Item.create( user_object.slice(*included_attributes.keys) )
#=> `Item` is created with only `name` attribute

Edit: as engineersmnky points out in the comments, row is already a hash. This simplifies it further, and you could instead just write:
SmarterCSV.process(file).each do |row|
  included_attributes = user.columns.select { |k, v| v == "true" }
  Item.create( row.slice(*included_attributes.keys) )
end

