一段将csv格式的db文件导入对应表结构的代码。

前提要求

  1. csv文件名字和Model Class需要一一对应, 比如用户表users, Model中定义是class User < ActiveRecord::Base, 那么csv文件名字得是user.csv
  2. csv文件需要有header,并且header名字需要同数据库中对应表的字段名相同

代码

以下代码在Rails 4.2下能够成功运行。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
require 'csv'
# 禁止Class的callback的函数
# https://stackoverflow.com/a/6538007
def skip_all_callbacks(klass)
[:validation, :save, :create, :commit].each do |name|
klass.send("_#{name}_callbacks").each do |_callback|
# HACK - the oracle_enhanced_adapter write LOBs through an after_save callback (:enhanced_write_lobs)
if (_callback.filter != :enhanced_write_lobs)
klass.skip_callback(name, _callback.kind, _callback.filter)
end
end
end
end
seed_files = Dir[Rails.root.join('lib', 'seeds', '*.csv')]
seed_files.each do |path|
model = "#{File.basename(path, '.*').camelize}".constantize
# 一些field可能并没有声明为attr_accessible, 因此在seeds中需要临时声明为attr_accessible, 否则对应的字段不会被更新,并且不会报错。
model.class_eval do
attr_accessible *column_names
end
# 设置要插入数据的model为禁止callback, 此处是纯粹的导入数据,所以需要禁止Model的callback,防止数据错乱。
skip_all_callbacks(model)
csv = CSV.parse(File.read(path), :headers => true, :encoding => 'ISO-8859-1')
csv.each do |row|
model.new(row.to_hash).save(validate: false)
end
end

运行

将代码保存为db/seeds.rb, 并将需要import的csv保存在lib/seeds/目录下。执行rake db:seed就可以将csv文件的数据导入到DB中对应的表中。

PostgreSQL dump命令

另外,在PostgreSQL中,将对应的某些记录dump成csv格式文件的命令如下:

1
2
# 在psql中输入如下命令,将所选记录dump成带header的csv文件
\copy (SELECT * FROM users where id >=10 and id <20) To '/tmp/user.csv' With CSV HEADER

留言