Importing CSV Data into Rails App, Using Something Other Then the Association "Id"

Importing CSV data into Rails app, using something other then the association id

A shipment_type is a ruby object, you want to send a string.

If you are needing to import relationships, add methods on the Port model like so

class Port < ApplicationRecord

def shipment_type_name
shipment_type.try(:name)
end

def shipment_type_name=(name)
self.shipment_type = ShipmentType.where(:name => name).first_or_create
end

def country_country_code
country.try(:country_code)
end

def country_country_code=(code)
self.country = Country.where(:country_code => code).first
end

end

Then in the CSV you'd send a shipment_type_name and country_country_code attributes.

You would do something similar to other relationships.

When importing a CSV, how do I handle data in a row that corresponds to an association?

try this

def self.import(file)
CSV.foreach(file.path, headers: true) do |row|
product = find_by_id(row["id"]) || new
product.attributes = row.to_hash.slice(*accessible_attributes)
product.save!

building = product.buildings.find_by_name(row['building_name'])
building ||= product.buildings.build
building.attributes = row.to_hash.slice(*build_accessible_attributes)
building.save!
end
end

UPDATE: updated answers using new rails 3 methods

def self.import(file)
CSV.foreach(file.path, headers: true) do |row|
product = where(id: row["id"])
.first_or_create!(row.to_hash.slice(*accessible_attributes))

product.buildings.where(name: row['building_name'])
.first_or_create!(row.to_hash.slice(*building_accessible_attributes))
end
end

ActiveRecord::AssociationTypeMismatch Rails CSV Import

I managed to get a solution to this, thanks to a wonderfully detailed question and great answer provided here Importing CSV data into Rails app, using something other then the association "id"

Rails CSV import, adding to a related table

You can do this by adding a simple loop after your "normal" data is added to the model, and using the << method to append to the years association.

...
course.value = row[3]
course.pass_mark = row[4]
5.upto(8).each do |i|
one_year = Year.find(row[i])
course.years << one_year if one_year
end
if course.save
n = n+1
...

You can add more checks in the loop if you want to make sure that the values are valid, and/or change the find to locate your year in another way. Another way when the related data is "trailing off the end" like this is to keep adding until there is nothing left to add, and also to add the years themselves if they don't exist yet:

...
course.value = row[3]
course.pass_mark = row[4]
row[5..-1].each do |year_id|
one_year = Year.find_or_create_by_id(year_id)
course.years << one_year
end
if course.save
n = n+1
...

There are a lot of different ways to do this, and the way which is right is really dependent on your actual data, but this is the basic method.

Associating rows from uploaded CSV files with a User in rails

You're not passing in the user id so merge the user_id onto your hash:

def self.import(file, user_id)
CSV.foreach(file.path, headers: true) do |row|
Sample.import(params[:file], current_user.id)
end
end
end

You could find the user and do it through an association to ensure the user exists - how you want to deal with it not existing I leave to you. Using find_by so it doesn't throw an active record not found error, if you want that then just use find instead.

def self.import(file, user_id)
user = User.find_by(id: user_id)
if user
CSV.foreach(file.path, headers: true) do |row|
user.samples.create! row.to_hash
end
end
end
end

Rails upload csv or text file with associations

Ok - doing a lot of communication in the comments and I think I can put together an answer now.

So, as per my edit to pitabas prathal's answer, you need to look for by the :code key in the code_params hash, but since the Code class has no idea that you've got a code_params[:software_id] to refer to, you'll need to pass that along. So your import method becomes:

code.rb

def self.import(file, software_id)
CSV.foreach(file.path, headers: true) do |row|
code = Code.new row.to_hash
code.software_id = software_id
code.save!
end
end

Then, your call to this method with the new argument, from the create action (or your import method on the controller):

Code.import(code_params[:code], code_params[:software_id])

Now, you are giving your Code class all the information it needs to associate the new Code objects with the appropriate Software object.

Edit

In your GoRails post, Chris Oliver's answer would also work, with one edit:

@software = Software.find(params[:software_id])

will not work - params[:software_id] is nil. You can access software_id from the code_params hash:

@software = Software.find(code_params[:software_id])

or by adding the [:code] key in to the params reference like so:

@software = Software.find(params[:code][:software_id])

since [:software_id] is inside the [:code] array in the params hash.

Rails csv import with associations

I was able to solve this with help from Chris at gorails.com. Here is my (rough) working solution. Hope this helps anyone else with this issue!

require 'csv'
require 'open-uri'
namespace :post_import do
desc "Import posts daily"
task posts: :environment do
filename = File.join Rails.root, "posts.csv"
counter = 0

CSV.foreach(filename) do |row|
name, category_ids, description = row
post = Post.new(name: name, description: description) if post == nil
post.save

#separate string of category ids into array
a_categories = category_ids.split(",")

a_categories.each do |category_id|
post.styles.where(category_id: category_id).first_or_create
end

counter += 1 if post.persisted?
end

puts "Imported #{counter} [posts]
end
end

Add Project on CSV upload

The Process of writing out my code above helped me realise.

I just had to change one line in my import

from

def import
Item.import(params[:file])
redirect_to projects_path(@project), notice: "Sucessfully Added Items"
end

to

def import
@project = Project.find(params[:project_id])
@project.items.import(params[:file])
redirect_to projects_path(@project), notice: "Sucessfully Imported Items!"
end


Related Topics



Leave a reply



Submit