我想将数据从CSV文件导入到现有的数据库表中。我不想保存CSV文件,只是从它的数据,并把它放入现有的表。我使用Ruby 1.9.2和Rails 3。

这是我的桌子:

create_table "mouldings", :force => true do |t|
  t.string   "suppliers_code"
  t.datetime "created_at"
  t.datetime "updated_at"
  t.string   "name"
  t.integer  "supplier_id"
  t.decimal  "length",         :precision => 3, :scale => 2
  t.decimal  "cost",           :precision => 4, :scale => 2
  t.integer  "width"
  t.integer  "depth"
end

你能给我一些代码,告诉我最好的方法,谢谢。


当前回答

更好的方法是将其包含在rake任务中。创建导入。Rake文件在/lib/tasks/中,并将此代码放到该文件中。

desc "Imports a CSV file into an ActiveRecord table"
task :csv_model_import, [:filename, :model] => [:environment] do |task,args|
  lines = File.new(args[:filename], "r:ISO-8859-1").readlines
  header = lines.shift.strip
  keys = header.split(',')
  lines.each do |line|
    values = line.strip.split(',')
    attributes = Hash[keys.zip values]
    Module.const_get(args[:model]).create(attributes)
  end
end

然后在您的终端上运行此命令rake csv_model_import[file.csv,Name_of_the_Model]

其他回答

require 'csv'    

csv_text = File.read('...')
csv = CSV.parse(csv_text, :headers => true)
csv.each do |row|
  Moulding.create!(row.to_hash)
end

如果您想使用SmartCSV

all_data = SmarterCSV.process(
             params[:file].tempfile, 
             { 
               :col_sep => "\t", 
               :row_sep => "\n" 
             }
           )

这表示每个行“\t”中以制表符分隔的数据,行由新行“\n”分隔

你可以试试Upsert:

require 'upsert' # add this to your Gemfile
require 'csv'    

u = Upsert.new Moulding.connection, Moulding.table_name
CSV.foreach(file, headers: true) do |row|
  selector = { name: row['name'] } # this treats "name" as the primary key and prevents the creation of duplicates by name
  setter = row.to_hash
  u.row selector, setter
end

如果这是您想要的,您还可以考虑从表中删除自动递增的主键,并将主键设置为name。或者,如果有一些组成主键的属性组合,则将其用作选择器。不需要索引,这样会更快。

smarter_csv gem是专门为这个用例创建的:从CSV文件读取数据并快速创建数据库条目。

  require 'smarter_csv'
  options = {}
  SmarterCSV.process('input_file.csv', options) do |chunk|
    chunk.each do |data_hash|
      Moulding.create!( data_hash )
    end
  end

您可以使用chunk_size选项一次读取N个csv-行,然后在内部循环中使用Resque生成将创建新记录的作业,而不是立即创建它们——这样您就可以将生成条目的负载分散到多个工作者。

参见: https://github.com/tilo/smarter_csv

更好的方法是将其包含在rake任务中。创建导入。Rake文件在/lib/tasks/中,并将此代码放到该文件中。

desc "Imports a CSV file into an ActiveRecord table"
task :csv_model_import, [:filename, :model] => [:environment] do |task,args|
  lines = File.new(args[:filename], "r:ISO-8859-1").readlines
  header = lines.shift.strip
  keys = header.split(',')
  lines.each do |line|
    values = line.strip.split(',')
    attributes = Hash[keys.zip values]
    Module.const_get(args[:model]).create(attributes)
  end
end

然后在您的终端上运行此命令rake csv_model_import[file.csv,Name_of_the_Model]