我想将数据从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
你能给我一些代码,告诉我最好的方法,谢谢。
下面的模块可以在任何模型上进行扩展,它将根据CSV中定义的列标题导入数据。
注意:
这是一个很棒的内部工具,对于客户使用,我建议添加安全措施和消毒
CSV中的列名必须与DB模式完全相同,否则将无法工作
通过使用表名获取头信息,而不是在文件中定义头信息,可以进一步改进
创建一个名为“csv_importer”的文件。在您的模型/关注点文件夹中
module CsvImporter
extend ActiveSupport::Concern
require 'csv'
def convert_csv_to_book_attributes(csv_path)
csv_rows = CSV.open(csv_path).each.to_a.compact
columns = csv_rows[0].map(&:strip).map(&:to_sym)
csv_rows.shift
return columns, csv_rows
end
def import_by_csv(csv_path)
columns, attributes_array = convert_csv_to_book_attributes(csv_path)
message = ""
begin
self.import columns, attributes_array, validate: false
message = "Import Successful."
rescue => e
message = e.message
end
return message
end
end
将扩展CsvImporter添加到您想要扩展此功能的任何模型中。
在你的控制器中,你可以像下面这样使用这个功能:
def import_file
model_name = params[:table_name].singularize.camelize.constantize
csv = params[:file].path
@message = model_name.import_by_csv(csv)
end
下面的模块可以在任何模型上进行扩展,它将根据CSV中定义的列标题导入数据。
注意:
这是一个很棒的内部工具,对于客户使用,我建议添加安全措施和消毒
CSV中的列名必须与DB模式完全相同,否则将无法工作
通过使用表名获取头信息,而不是在文件中定义头信息,可以进一步改进
创建一个名为“csv_importer”的文件。在您的模型/关注点文件夹中
module CsvImporter
extend ActiveSupport::Concern
require 'csv'
def convert_csv_to_book_attributes(csv_path)
csv_rows = CSV.open(csv_path).each.to_a.compact
columns = csv_rows[0].map(&:strip).map(&:to_sym)
csv_rows.shift
return columns, csv_rows
end
def import_by_csv(csv_path)
columns, attributes_array = convert_csv_to_book_attributes(csv_path)
message = ""
begin
self.import columns, attributes_array, validate: false
message = "Import Successful."
rescue => e
message = e.message
end
return message
end
end
将扩展CsvImporter添加到您想要扩展此功能的任何模型中。
在你的控制器中,你可以像下面这样使用这个功能:
def import_file
model_name = params[:table_name].singularize.camelize.constantize
csv = params[:file].path
@message = model_name.import_by_csv(csv)
end
我知道这是一个老问题,但它仍然在谷歌的前10个链接。
逐个保存行不是很有效,因为它会导致循环中的数据库调用,您最好避免这种情况,特别是当您需要插入大量数据时。
使用批处理插入更好(而且更快)。
INSERT INTO `mouldings` (suppliers_code, name, cost)
VALUES
('s1', 'supplier1', 1.111),
('s2', 'supplier2', '2.222')
您可以手动构建这样的查询,而不是使用Model.connection。执行(原始SQL字符串)(不推荐)
或者使用gem activerecord-import(它于2010年8月11日首次发布)在这种情况下,只需将数据放在数组行中并调用Model。进口的行
详情请参阅gem文档