2017-06-06 66 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))