2

I've a rake task where I import CSV data into a database via Rails.

I want a specific column (specifically, row[6] below) to be rendered as an integer. However, everything I try returns that value as a string.

Below is the rake task:

require 'csv'
namespace :import_site_csv do
  task :create_sites => :environment do
    CSV.foreach('../sites.csv', :headers => true) do |row|
        row[6] = row[6].to_i
        Site.create!(row.to_hash)
    end
  end
end 

Does anyone have an idea how I might do this? Thanks!

1
  • What I realized (to my embarrassment) was that in the migration itself that created the table into which the data was being dumped, I specified there that the field row[6] populated was a string. Once I changed t.string to t.integer, it worked perfectly. Commented Jul 15, 2016 at 16:09

1 Answer 1

1

You are making one small (but important) mistake here.

When you call CSV.foreach('../sites.csv') each of the rows will be an array of the values in that particular row. That would allow you to access the data you need, in the way you do it now - row[6].

But, when you add the :headers => true option to CSV.foreach, you will not get an array of values (row will not be an array). Instead, it will be a CSV::Row object (docs). As you can read in the documentation:

A CSV::Row is part Array and part Hash. It retains an order for the fields and allows duplicates just as an Array would, but also allows you to access fields by name just as you could if they were in a Hash.

For example, if you have a column with the name Title in the CSV, to get the title in each of the rows, you need to do something like:

CSV.foreach('file.csv', :headers => true) do |row|
    puts row['Title']
end

Since I do not know the structure of your CSV, I cannot tell you which key you should use to get the data and convert it to an Integer, but I think that this should give you a good idea of how to proceed.

Sign up to request clarification or add additional context in comments.

6 Comments

Thanks, Ile! This is good information. Unfortunately, I'm still having the problem. I can access the value (row[6] or more specifically, row['trust_id']) and convert it to an integer initially. However, during the course of the Site.create!(row.to_hash), it converts the value back into a string. Do you have any idea why that would do that?
Absolutely! Here is a sample from the CSV file, which includes the header: name,city,state,country,start_date,end_date,trust_id,site_code MONKEY-SYSTEMs,CLEVELAND,OH,USA,1/2/1968,1/2/1968,1,ABEST-0481
And below is code I tried afterward: CSV.foreach('../sample_sites.csv', :headers => true) do |row| row['trust_id'] = row['trust_id'].to_i puts(row['trust_id'].is_a? Integer) Site.create!(row.to_hash) The puts outputs true, signaling the value is an integer at that point, but then when Site.create runs, the value in the row is converted back to a string.
Actually, I just tested your code and it works. It returns the following: {"name"=>"MONKEY-SYSTEMs", "city"=>"CLEVELAND", "state"=>"OH", "country"=>"USA", "start_date"=>"1/2/1968", "end_date"=>"1/2/1968", "trust_id"=>1, "site_code"=>"ABEST-0481"}. I am not sure if you can spot it, but the trust_id is an integer (does not have the quotes around it). Could it be that you are having another issue, and not with the CSV?
I think I just figured it out. Thanks so much for your help! I owe you a beer next time I'm in Amsterdam!
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.