2017-08-09 55 views
0

我想上传一个CSV文件导入到现有的数据库,并接受下列未知属性错误上传

error: ActiveRecord::RecordInvalid in UploadsController#import! Validation failed: Email has already been taken.

控制器

class UploadsController < ApplicationController 
    def index 
    @uploads = Upload.all 
    end 

    def import 
    Upload.import(params[:file]) 
    redirect_to uploads_path, notice: "Employee data imported!" 
    end 
end 

型号

class Upload < ActiveRecord::Base 
    require 'csv' 

    def self.import(file) 
    CSV.foreach(file.path, headers: true) do |row| 
     Employee.create! row.to_hash 
    end 
    end 
end 

create_table "employees", force: :cascade do |t| 
    t.string "last_name" 
    t.string "first_name" 
    t.string "employee_code" 
    t.string "email" 
    t.string "level" 
    t.string "dept" 
    t.datetime "created_at", null: false 
    t.datetime "updated_at", null: false 
end 

我检查,并为员工我的数据库头不符合我的CSV文件(开始第1行,第1栏)的第一行。有什么想法吗?

+1

您可以添加迁移以将新属性'last_name'添加到employees表中。 – akbarbin

+0

同时仔细检查您正在运行上载的数据库是否是您手动检查列的相同数据库....即,如果您最近将该列添加到了开发中,并且它尚未投入生产,等等。 –

+0

感谢@MuhamadAkbarBinWidayat。见下文。我把'last_name'作为我的表中的一列。除非我错过了一些不知道该怎么做的事情。 – jarlyon

回答

0

您提供给Employee.create!(本例中为CSV标头)的哈希键需要与模型上属性的名称完全匹配。您的问题可能是由以下一项或多项原因造成的:

  • 有一列的标题并非全部为小写。例如,CSV列名可以是“电子邮件”或“电子邮件”,但应该是“电子邮件”。
  • 有一个标题中有空格的列。例如,CSV列名可以是“名”或“姓”,但应分别是“first_name”或“last_name”。
  • 在CSV中存在一列,其中列标题拼写错误,或者根本不属于数据库中的表模式。 (虽然你说你所有的CSV栏标题匹配的数据库表列,也许再次检查,如果问题不是由前两个子弹解决。)

上述任何一个会引起你所看到的ActiveModel::UnknownAttributeError 。如果问题是由上述一个或多个问题引起的,那么您可以通过编辑CSV文件来明确解决问题,以确保每个标头都带有下划线而不是空格。或者,你可以在:header_converters => :symbol选项传递给CSV.foreach这样的:

CSV.foreach(file.path, headers: true, header_converters: :symbol) do |row| 
    Employee.create! row.to_hash 
end 

此选项将它们转换为小写,用下划线代替空格,然后将它们转换为符号改变你的头。如果您需要清理很多列标题,或者如果您经常收到带有“稍差”标题的文件,并且遇到上述问题之一,那么这可能是更可靠的选项。

编辑

我看到了有关该错误的更多详细更新你的问题。 Rails告诉你,CSV中有一个标题为“last_name”的列,但数据库中没有这样的列(即Employee模型中没有这样的属性)。正如穆罕默德所建议的那样,您可以创建一个迁移来将last_name列添加到Employee。你能否验证你的雇员表在数据库中有这个专栏?

+0

谢谢@drse。我试过谢谢 - 我添加了':header_converters =>:symbol'现在得到了一个不同的错误。看到我的初始职位,为新的错误和表 – jarlyon