Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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.

enter image description here

enter image description here

enter image description here

like image 220
vinicomelo Avatar asked Oct 30 '22 11:10

vinicomelo


1 Answers

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.

like image 107
Mark Swardstrom Avatar answered Nov 15 '22 07:11

Mark Swardstrom