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
How to Build Ruby 2.1.3 on Osx 10.10 Gm 3.0 with Rbenv
How to Change Ruby to Version 1.9.3 (Again) with Rvm
How to Run an Excel MACro from Ruby
Project Euler #3 in Ruby Solution Times Out
How Is Ruby Tcpsocket Timeout Defined
Require Command Not Working Within Bash Irb on Snow Leopard
When to Use Association Extensions VS Named Scopes
Encrypting/Decrypting 3Des in Ruby
Error Installing "Kgio-2.9.2" Gem on Windows
Rails 4 Many to Many Association Not Working
Nested Form_For Singular Resource
Can't Setup Ruby Environment - Installing Fii Gem Error
Capybara Trouble Filling in Js Modal
Why Does Date.Yesterday Counts as Date.Today Also