2014-10-30 42 views
2

我試圖使用Roo gem基於http://railscasts.com/episodes/396-importing-csv-and-excel將CSV和Excel文件導入到rails 4項目(帶驗證)中。Roo with rails4給出了未定義的方法`[]'爲零:NilClass

我已經做了一些改動,以考慮Rails4代替Rails3中和改變小豆,我ProjectImporter模型現在看起來像:

class ProductImport 
    include ActiveModel::Model 
    attr_accessor :file 

    def initialize(attributes = {}) 
    attributes.each { |name, value| send("#{name}=", value) } 
    end 

    def persisted? 
    false 
    end 

    def save 
    if imported_products.map(&:valid?).all? 
     imported_products.each(&:save!) 
     true 
    else 
     imported_products.each_with_index do |product, index| 
     product.errors.full_messages.each do |message| 
      errors.add :base, "Row #{index + 2}: #{message}" 
     end 
     end 
     false 
    end 
    end 

    def imported_products 
    @imported_products ||= load_imported_products 
    end 

    def load_imported_products 
    spreadsheet = open_spreadsheet 
    spreadsheet.default_sheet = spreadsheet.sheets.first 
    puts "!!! Spreadsheet: #{spreadsheet}" 
    header = spreadsheet.row(1) 
    (2..spreadsheet.last_row).map do |i| 
     row = Hash[[header, spreadsheet.row(i)].transpose] 
     product = Product.find_by(id: row['id']) || Product.new 
     product.attributes = row.to_hash.slice(*['name', 'released_on', 'price']) 
     product 
    end 
    end 

    def open_spreadsheet 
    case File.extname(file.original_filename) 
     when ".csv" then 
     Roo::CSV.new(file.path, nil) 
     when '.tsv' then 
     Roo::CSV.new(file.path, csv_options: { col_sep: "\t" }) 
     when '.xls' then 
     Roo::Excel.new(file.path, nil, :ignore) 
     when '.xlsx' then 
     Roo::Excelx.new(file.path, nil, :ignore) 
     when '.ods' then 
     Roo::OpenOffice.new(file.path, nil, :ignore) 
     else 
     raise "Unknown file type #{file.original_filename}" 
    end 
    end 
end 

當我嘗試運行導入(使用測試CSV數據),它在header = spreadsheet.row(1)上失敗,錯誤號爲undefined method '[]' for nil:NilClass。我列出的額外puts聲明確認spreadsheet本身不是零:它給出!!! Spreadsheet: #<Roo::CSV:0x44c2c98>。但是,如果我嘗試調用幾乎所有的預期方法,例如#last_row,它會給我提供相同的未定義方法錯誤。

那麼我做錯了什麼?

+1

它可能告訴你到底發生了什麼行'NilClass'錯誤。請提供。 – deefour 2014-10-30 16:33:59

+0

我已經提供了。正如我寫的,「它在'header = spreadsheet.row(1)'」上失敗。這是'load_imported_products'的第4行,在插入調試'puts'後立即檢查'spreadsheet'不是'nil'。 – digitig 2014-11-04 09:15:56

+1

'.row(1)'不是方法'[]'。發生錯誤時,我要求提供完整的調用堆棧。 '[]'可能來自Roo內部 - 您應該在調用堆棧中看到一行引用該行。 '.row(1)'就是您所做的失敗的API調用,會觸發錯誤。 – deefour 2014-11-04 13:10:34

回答

7

我有同樣的問題,它似乎是一個關於文件enconding的問題,我用這個代碼,它是固定的。

def open_spreadsheet 
    case File.extname(file.original_filename) 
     when ".csv" then Roo::CSV.new(file.path, csv_options: {encoding: "iso-8859-1:utf-8"}) 
     when ".xls" then Roo::Excel.new(file.path, nil, :ignore) 
     when ".xlsx" then Roo::Excelx.new(file.path, nil, :ignore) 
     else raise "Unknown file type: #{file.original_filename}"   
    end 
end 

我希望對你有幫助。

+0

在指定之前,什麼是默認編碼? – jayant 2016-05-05 08:46:11

+0

另外,謝謝! :) – jayant 2016-05-05 09:01:13

相關問題