Reputation: 81
I have tried to import a CSV file into ruby on rails using many scripts and methods and nothing seems to work. I have been hoping that code from Erik on Rails blog will help to get my job done.
I put this script into lib/tasks/import.rake:
desc "Imports a CSV file into an ActiveRecord table"
task :csv_model_import, [:filename, :model, :needs] => [:environment] do |task,args|
lines = File.new(args[:filename]).readlines
header = lines.shift.strip
keys = header.split(',')
lines.each do |line|
values = line.strip.split(',')
attributes = Hash[keys.zip values]
Module.const_get(args[:model]).create(attributes)
end
end
I created a model in the rails console
rails generate model SomeModel
then ran this in the rails console
rake csv_model_import[somefile.csv,SomeModel]
After running this, the cursor just returns in the console. It fails silently. When viewing the database file for the rails program, the table is empty after the import. It has filed to import the data.
I tried something else as well. I tried first creating a model with the fields and types defined before running the rake import command. This also failed in the same way.
I am very new to Ruby on Rails and I am. I have spent 2 days trying to get a CSV file into Ruby on Rails and would greatly appreciate some help. Please let me know how to proceed, Thanks so much guys.
Upvotes: 0
Views: 362
Reputation: 4164
Following on your approach and why you may not be getting anything:
When I tried to replicate the error, the following is what I found out:
the line
lines = File.new(args[:filename]).readlines
reads the file in as one element separated by commas(,) for cells and new lines (\r or \n) for new lines... e.g:["name,age,food\rtabitha,2,carrots\relijah,1,lettuce\rbeatrice,3,apples"]
This is the major problem because the blog post probably had another format gotten, on which the rest of the code is based on.
With this output, however... performing the shifting and splitting and stripping as above yields no result.
What I then did was to work off based on the result with the following steps:
1) Get the content:
file = File.new(args[:filename]).readlines => ["name,age,food\rtabitha,2,carrots\relijah,1,lettuce\rbeatrice,3,apples"]
2) Parse into a desired format by splitting on the new-lines (\r in my case)
lines = file.shift.strip.gsub(/\r/,"\\").split(/\\/) => ["name,age,food", "tabitha,2,carrots", "elijah,1,lettuce", "beatrice,3,apples"]
3) Get the headers:
header = lines.first => "name,age,food"
4) Get the body:
body = lines[1..-1] => ["tabitha,2,carrots", "elijah,1,lettuce", "beatrice,3,apples"]
5) Get keys from header:
keys = header.split(',') => ["name", "age", "food"]
6) Loop through the body and create objects in the database:
body.each do |line|
values = line.strip.split(',')
attributes = Hash[keys.zip values]
Module.const_get(args[:model]).create(attributes)
end
The full gist is as follow:
desc "Imports a CSV file into an ActiveRecord table"
task :csv_model_import, [:filename, :model, :needs] => [:environment] do |task,args|
file = File.new(args[:filename]).readlines
lines = file.shift.strip.gsub(/\r/,"\\").split(/\\/)
header = lines.first
body = lines[1..-1]
keys = header.split(',')
body.each do |line|
values = line.strip.split(',')
attributes = Hash[keys.zip values]
Module.const_get(args[:model]).create(attributes)
end
end
PS: I notice the comment on ProgNoob's answer. you have to create a model first with all the needed attributes and have the database migrated. Then you can pass the model name and the csv file name into the rake file.
In my case, I have a model Somemodel
generated as follow:
rails g model somemodel name:string age:string food:string
Notice that I added all the desired attributes.
And then migrated my database as:
$ rake db:migrate
Upvotes: 1