I am trying to import a few CSV files into my rails app. I learned and managed to import tables into Models without association.
Now i have managed to import the data into a table that has associations, but only by entering the actual "id" number on the CSV column. Although functional, this isn't really an option because i have many tables with thousands of IDs.
My main goal is to be able to use the column in the CSV and type in the actual value (that exists in the other model it is associated with), instead of the id number.
I have a Country model and a Ports model. The Ports model is associated with country_id
Port Model
class Port < ApplicationRecord
def self.import(file)
#code
CSV.foreach(file.path, headers: true) do |row|
port = find_by_id(row["id"])
Port.create! row.to_hash
end
end
belongs_to :shipment_type
belongs_to :country
has_many :origins, :class_name => 'Rate'
has_many :destinations, :class_name => 'Rate'
end
Country Model
class Country < ApplicationRecord
def self.import(file)
#code
CSV.foreach(file.path, headers: true) do |row|
Country.create! row.to_hash
end
end
has_many :ports, dependent: :destroy
end
schema.db
create_table "ports", force: :cascade do |t|
t.string "name"
t.string "port_code"
t.integer "shipment_type_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "country_id"
t.index ["country_id"], name: "index_ports_on_country_id", using: :btree
t.index ["shipment_type_id"], name: "index_ports_on_shipment_type_id", using: :btree
end
create_table "countries", force: :cascade do |t|
t.string "name"
t.string "country_code"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "shipment_types", force: :cascade do |t|
t.string "name"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
The associations are working because i am able to manually add them view my forms i create just fine.
<%= form_for(port) do |f| %>
<% if port.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(port.errors.count, "error") %> prohibited this port from being saved:</h2>
<ul>
<% port.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :name %>
<%= f.text_field :name %>
</div>
<div class="field">
<%= f.label :port_code %>
<%= f.text_field :port_code %>
</div>
<div class="field">
<%= f.label :shipment_type_id %>
<%= f.collection_select :shipment_type_id, ShipmentType.all, :id, :name %>
</div>
<div class="field">
<%= f.label :country_code %>
<%= f.collection_select :country_id, Country.all, :id, :country_code %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
Any guidance or help would be greatly appreciated. I have been going in circles with this for days now.
ADDING SAMPLE TABLE FROM CSV FILE.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With