Rails 4 CSV is loaded into multiple models
I am trying to load a csv file that has data that belongs to two different models: Project
and PurchaseOrder
. I am using communication has_many, :through
between models.
I have problems downloading. I have included common attributes in both controllers and included accepts_nested_attributes
in both models.
Here's my code to read in csv.
def self.import(file)
CSV.foreach(file.path, headers: true) do |row|
project_hash = row.to_hash
project = Project.where(project_name: project_hash["project_number"]).first
if project.present?
project.first.update_attributes(project_hash)
else
Project.create! (project_hash)
end
purchase_order = PurchaseOrder.where(po_number: project_hash["po_number"]).first
if purchase_order.present?
PurchaseOrder.create!
end
I have two questions / problems.
-
I cannot read the attribute
po_number
. I am getting this errorunknown attribute 'po_number' for Project
. -
I don't know how to push the generated purchase order to the project hash so that it updates the value of the attached attribute.
Thanks in advance to everyone who can help!
**** Update With this method, the data is stored in the correct tables. However, the link between PurchaseOrder and Project is not preserved. Any thoughts?
def self.import(file)
CSV.foreach(file.path, headers: true) do |row|
project_hash = row.to_hash
po_hash = {}
po = PurchaseOrder.new
project_hash.each { |k, v| po_hash[k] = project_hash.delete(k) if po.respond_to?(k) }
project = Project.where(project_name: project_hash["project_number"]).first
if project.present?
project.first.update_attributes(project_hash)
else
Project.create! (project_hash)
end
po = PurchaseOrder.where(po_number: po_hash["po_number"]).first
if po.present?
po.first.update_attributes(po_hash)
else
PurchaseOrder.create! (po_hash)
end
end
end
source to share
These lines are trying to update / build the project using all the values ββin the hash ...
project.first.update_attributes(project_hash)
...
Project.create! (project_hash)
But obviously some hash items (eg "po_number") do not have columns in the projects table.
You need to split the csv hash elements based on which elements belong to which model ...
eg.
po_hash = {} po = PurchaseOrder.new project_hash.each { |k, v| po_hash[k] = project_hash.delete(k) if po.respond_to?(k) }
This will remove the PO fields from project_hash
and add them to po_hash
so you can use the correct hash to update the correct table.
To establish an association ...
change
Project.create!(project_hash)
in
project = Project.create!(project_hash)
so whether a project exists or is created, it is stored in the "project" variable. Similarly, do
po = PurchaseOrder.create!(po_hash)
Then after you've created or updated the PO, you can simply assign po to the project ...
project.purchase_orders << po
source to share