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

时间:2015-08-23 16:40:25

标签: ruby-on-rails csv ruby-on-rails-4 railscasts

所有源代码都托管在cloud_contacts repo。

中的GitHub上

我正在使用Rails Cast#396来使用Rails 4.我已经完成了它的工作 - 并且它将导入一个充满测试数据的文件。然后,它将在数据库中为我的.csv文件中的每个相应行(或联系人)创建一条记录。

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

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

所有源代码都托管在cloud_contacts repo。

中的GitHub上

但是如果你讨厌圣诞节和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

1 个答案:

答案 0 :(得分:1)

我对您的联系模式进行了一些更改,请参阅下面的评论。

聚苯乙烯。您可能会发现使用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