Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Importing CSV file into multiple models at one time

I have 3 models, Church, which has many Locations, which has many Pastors.

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

As you can see in my short block of code I am creating a Church and its first location. How would I also add a pastor to that?

For instance will this work?

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

Is there another way I should be going about this? Trying to move thousands of records from one rails app to another.

like image 601
Aaron Mills Avatar asked Dec 19 '12 03:12

Aaron Mills


1 Answers

I take a slightly different approach to this, I have found a two step process is easier to use and build on.

The first step is load the data.

I use two 'staging' tables.
Something like:

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. 
...

So I load the testimport.csv directly into these loading tables - which support multiple runs if you make the run_number unique (sequence, etc.)

Now you have the data in sql and available in rails.

Now write the code to actually populate the application tables from this loading area.

This will also help you with the speed issue. Rails will only be inserting a few records per second, so you want to be able to do restarts, pauses, etc.

This will also help with validation. Initially you just want to load the data, regardless of any constraints (not null, unique, etc.).

Once loaded into staging you can be more selective and apply validations as you wish.

like image 141
Michael Durrant Avatar answered Oct 12 '22 22:10

Michael Durrant