2017-06-06 51 views
1

我有一个模型“项目”,我想生成一堆项目与从CSV文件中获取的数据。但我想让用户选择使用哪些数据列。如何动态生成创建方法的参数?

所以我的模型“用户”有一个名为列的json属性,告诉哪些列应该从该用户的CSV文件中使用。例如,如果user.columns == {"title"=>"true","category"=>"false"},则应使用标题列,但类别列不应。 (或者,我可以只列出我想包括列,像这样:{"title"=>"included"},后来做类似user.columns.each {|c| c[0]}得到所有包含列阵列)

我有生成项目的方法基于CSV数据:

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 

,但我怎么能修改的基础上user.columns内容的方法的参数?对于{"title"=>"true","category"=>"false"}示例,该方法仅为Item.create(name: row[:title])。是否有可能动态生成这样的方法?

我打算有相当多的可能的列,所以做一个if有条件的每一种可能性是不可行的。

+0

目前还不清楚列名与您在'create'参数中需要的对应关系。但似乎你应该修改'user.columns'来返回别的东西(或者提供其他用户方法来这样做) –

+0

@MarkThomas对不起,如果我不清楚,我想根据内容为我的'create'动作生成参数'user.columns'。例如,如果'user.columns = {“included_column”=>“true”,“another_included_column”=>“true”,“not_included_column”=>“false”}',那么'create'参数就是Item。 create(included_column:row [:included_column],another_included_column:row [:another_included_column])''。那有意义吗? 'not_included_column'不会是一个参数,因为它在'user.columns'中是错误的。 –

+0

'row'包含什么? –

回答

2

Item.create(name: row[:name])还需要一个散列值,和可以等效地写成Item.create({ name: row[:name] })

这样 - 你可以建立在每个时间的哈希整个对象;然后slice关闭您不想要的任何属性,然后传递给create。因此,假如您有:

user.columns 
#=> {"name"=>"true","category"=>"false"} 

然后,你可以写:

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 

编辑:作为engineersmnky在评论中指出,row已经是一个哈希值。这进一步简化它,你可以改为只写:

SmarterCSV.process(file).each do |row| 
    included_attributes = user.columns.select { |k, v| v == "true" } 
    Item.create(row.slice(*included_attributes.keys)) 
end 
+1

行已经是'Hash'并且具有'name'和'category'的键,为什么不只是利用它呢? – engineersmnky

+0

@engineersmnky:好点! – gwcodes

+1

'keys.map(&:to_sym)':)因为“行”键显然是符号而列键是字符串。或者用'symbolize_keys'预处理user.columns' – engineersmnky

1

我想补充的方法,以你的User型号为符号返回列名:

class User 
    def selected_columns 
    columns.select{|_,v| v == "true"}.keys.map(&:to_sym) 
    end 
end 

,然后修改您的项目创造像所以:

Item.create(row.slice(*user.selected_columns))