Importing CSV into Rails
I had a code challenge for a company where I had to load a flat file of data from an Excel spreadsheet into a database. This is a quick guide to teach you how to load a CSV datatype file into your Rails backend.
First, create a table with the same number of columns and column names as the columns in your CSV.
Next, install the CSV gem:
gem install csv
In seeds.rb:
require 'csv' filename = "YourFilePath"csv = CSV.parse(filename, :headers => true)
csv.each do |row|
YourTable.create!(row.to_hash)
end
This may be all that you need to do to get this to seed. I however hit the below errors and had to modify this.
`require’: no such file to load — iconv (LoadError)
The solution to this error stated in the StackOverflow post is to add this to your Gemfile and bundle install:
gem "iconv", "~> 1.0.3"
I also had to convert the hash keys to lowercase:
require 'csv'filename = "YourFilePath"CSV.foreach(filename, :headers => true) do |row|
new_hash = {}
row.to_hash.each_pair do |k,v|
new_hash.merge!({k.downcase => v})
endYourTable.create!(new_hash)
end
The next error I got was:
ArgumentError: invalid byte sequence in UTF-8
The solution was to add:
CSV.foreach(file.path, headers: true, encoding:'iso-8859-1:utf-8') do |row|
...
end
The next roadblock was that the CORS Policy was blocking my requests. This StackOverflow post provides this solution:
1st Step: add gem to your Gemfile:
gem 'rack-cors', :require => 'rack/cors'
and then save and run bundle install
2nd Step: update your config/application.rb file by adding this:
config.middleware.insert_before 0, Rack::Cors do
allow do
origins '*'
resource '*', :headers => :any, :methods => [:get, :post, :options]
end
end
Finally, my seeds.rb ended up looking like this and seeded successfully:
require 'csv'filename = "/Users/Joseph/Documents/restaurant_grades_sample.csv"CSV.foreach(filename, :headers => true, encoding:'iso-8859-1:utf-8') do |row|
new_hash = {}
row.to_hash.each_pair do |k,v|
new_hash.merge!({k.downcase => v})
endGrade.create!(new_hash)
end
Sweet victory!