从 .csv 文件导入记录会在数据库中创建完全空白的行

importing records from .csv file creates completely blank rows in database

所有源代码都托管在我的 GitHub 的 cloud_contacts 存储库中。

我正在调整 Rails Cast #396 以与 Rails 一起工作 4. 我已经开始工作了 - 有点 - 它将导入一个充满测试数据的文件。然后它将在数据库中为我的 .csv 文件中的每个对应行(或联系人)创建一条记录。

我还可以在我的视图中手动添加新联系人,这是我自己构建的功能,与 Rails 演员表无关。

我的问题是,为什么每条联系人记录都是空白的?我认为问题出在我的 Contact 模型的导入方法上,也许当每个记录被转置时,header 中的列名与我数据库中的列名不匹配。如果是这种情况(我完全是在猜测...)我该如何解决?

所有源代码都托管在我的 GitHub 的 cloud_contacts 存储库中。

但如果你讨厌圣诞节并且 GitHub 并且不想看回购协议,这里是我的 Contact.rb 模型:

class Contact < ActiveRecord::Base
  # attr_accessible :first_name, :last_name, :email_address

  def self.import(file)
    spreadsheet = open_spreadsheet(file)
    header = spreadsheet.row(1)
    (2..spreadsheet.last_row).each do |i|
      row = Hash[[header, spreadsheet.row(i)].transpose]
      contact = find_by_id(row["id"]) || new
      contact.attributes = row.to_hash.slice(*accessible_attributes)
      # contact.attributes = row.to_hash.slice(*row.to_hash.keys)
      contact.save!
    end
  end

  def self.open_spreadsheet(file)
    case File.extname(file.original_filename)
      when ".csv" then Roo::CSV.new(file.path, csv_options: {col_sep: ";"})
      when ".xls" then Roo::Excel.new(file.path)
      when ".xlsx" then Roo::Excelx.new(file.path)
      else raise "Unknown file type: #{file.original_filename}"
    end
  end

  private

  def self.accessible_attributes
    [:first_name, :last_name, :email_address]
  end

end

这是我的 csv 文件中的一部分数据:

First Name  Last Name   Email Address   Phone Number    Company Name
Gerhard Kautzer gerhardkautzer@cronabayer.com   1-207-643-1816  Hodkiewicz-Lynch
Myra    Crona   myracrona@schinner.info (724)196-9470 x998  Champlin-Hahn
Josh    Donnelly    joshdonnelly@macejkovic.us  081-799-3139 x248   Casper Group
Verna   Farrell vernafarrell@schillercorkery.name   731.101.6219    Rosenbaum-Hane
Lauriane    Stracke laurianestracke@tremblayturner.biz  1-033-511-1831 x471 Prohaska-Sporer
Kaya    Luettgen    kayaluettgen@christiansen.name  (511)745-9273   Wyman, Trantow and Hane
Steve   Davis   stevedavis@shields.info 787.315.2611 x747   Kuhic-Lowe
Citlalli    Pfeffer citlallipfeffer@lemkeblanda.co.uk   329-584-6962 x047   Gorczany and Sons
Litzy   Turcotte    litzyturcotte@weber.name    1-084-641-4078 x4410    Hintz-Schmitt
River   Lockman riverlockman@shieldsgrant.ca    1-967-129-8359  Rowe LLC
Juvenal Berge   juvenalberge@nienow.co.uk   037-748-7238    Hane Inc

我对您的联系人模型做了一些更改,请参阅下面的评论。

Ps。您可能会发现使用 better_errors gem 可以帮助您了解变量在任何时候的样子。

class Contact < ActiveRecord::Base

  MAPPING = {
    "First Name" => "first_name",
    "Last Name" => "last_name",
    "Email Address" => "email_address"
  }

  def self.import(file)
    spreadsheet = open_spreadsheet(file)
    header = spreadsheet.row(1)
    (2..spreadsheet.last_row).each do |i|
      row = Hash[[header, spreadsheet.row(i)].transpose]
      # Convert the keys from the csv to match the database column names
      row.keys.each { |k| row[ MAPPING[k] ] = row.delete(k) if MAPPING[k] }
      # Remove company and phone number fields as these aren't in the database:
      create(row.except!('Company Name', 'Phone Number'))
    end
  end

  def self.open_spreadsheet(file)
    case File.extname(file.original_filename)
      # You're using a tab seperated file, so specify seperator as a tab with \t
      when ".csv" then Roo::CSV.new(file.path, csv_options: {col_sep: "\t"})
      when ".xls" then Roo::Excel.new(file.path)
      when ".xlsx" then Roo::Excelx.new(file.path)
      else raise "Unknown file type: #{file.original_filename}"
    end
  end

end