一次将CSV文件导入多个模型

时间:2012-12-19 03:06:39

标签: ruby-on-rails activerecord csv

我有3个模型,教堂,有很多地方,有很多牧师。

require 'csv'  
csvfile = File.read("testimport.csv")
csv = CSV.parse(csvfile, :headers => false)
csv.each do |row|
  c = Church.new
     c.name = row[0]
     c.url = row[10]
   c.locations.build(:address => row[3], :zipcode => row[5], :phone => row[6], :email => row[2], :city => row[4])
   c.save
end

正如您在我的短代码中所看到的,我正在创建一个教堂及其第一个位置。我怎么还要添加牧师?

例如,这会有效吗?

require 'csv'  
csvfile = File.read("testimport.csv")
csv = CSV.parse(csvfile, :headers => false)
csv.each do |row|
  c = Church.new
     c.name = row[0]
     c.url = row[10]
     location = c.locations.build(:address => row[3], :zipcode => row[5], :phone => row[6], :email => row[2], :city => row[4])
     location.pastors.build(:name => row[10])
     location.save
   c.save
end

我还有另一种方法吗?尝试将数千条记录从一个rails应用程序移动到另一个应用程序。

2 个答案:

答案 0 :(得分:1)

我对此略有不同,我发现两步过程更易于使用和构建。

第一步是加载数据。

我使用了两个'staging'表。
类似的东西:

staging_header
id           Integer  Unique  Primary Key
run_number   Integer  Unique
run_name     String

staging_data:
id                 Integer  Unique  Primary Key
staging_header_id  Integer
element1           String
element2           String
element3           String
uploaded?          Boolean  # Placed on the individual records allows restarts. 
...

所以我将testimport.csv直接加载到这些加载表中 - 如果你使run_number唯一(序列等),它支持多次运行

现在您拥有sql中的数据并且可以在rails中使用。

现在编写代码以实际填充此加载区域中的应用程序表。

这也可以帮助您解决速度问题。 Rails每秒只会插入几条记录,因此您希望能够重新启动,暂停等等。

这也有助于验证。最初,您只想加载数据,无论任何约束(非空,唯一等)。

加载到分段后,您可以更具选择性并根据需要应用验证。

答案 1 :(得分:0)

我能够让它工作,以下是我使用的。如果有更聪明的方法,请告诉我。注意:如果您尝试执行此操作,请将csv文件放在rails目录的根目录中,并在控制台中逐行执行此脚本。至少那就是我如何运作。

require 'csv'  
csvfile = File.read("testimport.csv")
csv = CSV.parse(csvfile, :headers => false)
csv.each do |row|
   c = Church.new
     c.name = row[0]
     c.url = row[10]
   c.locations.build(:title => "Sanctuary", :address => row[3], :zipcode => row[5],     :phone => row[6], :email => row[2], :city => row[4])
   c.save
loc = c.locations.first
loc.pastors.build(:firstname => row[1])
loc.save

end