使用关联“id”以外的其他内容将 CSV 数据导入 Rails 应用程序

vin*_*elo 5 ruby csv postgresql ruby-on-rails

我正在尝试将一些 CSV 文件导入到我的 rails 应用程序中。我学会并设法在没有关联的情况下将表导入到模型中。

现在我已经设法将数据导入到具有关联的表中,但只能通过在 CSV 列上输入实际的“id”编号。虽然功能齐全,但这并不是一个真正的选择,因为我有很多包含数千个 ID 的表。

我的主要目标是能够使用 CSV 中的列并输入实际值(存在于与其关联的其他模型中),而不是 ID 号。

我有一个 Country 模型和一个 Ports 模型。Ports 模型与 country_id 相关联

端口模型

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
Run Code Online (Sandbox Code Playgroud)

国家模式

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
Run Code Online (Sandbox Code Playgroud)

模式数据库

  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
Run Code Online (Sandbox Code Playgroud)

关联正在工作,因为我能够手动添加它们查看我创建的表单就好了。

<%= 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 %>
Run Code Online (Sandbox Code Playgroud)

任何指导或帮助将不胜感激。这几天我一直在绕圈子。

从 CSV 文件添加样本表。

在此处输入图片说明

在此处输入图片说明

在此处输入图片说明

Mar*_*rom 2

Shipment_type 是一个 ruby​​ 对象,您要发送一个字符串。

如果您需要导入关系,请在Port模型上添加方法,如下所示

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
Run Code Online (Sandbox Code Playgroud)

然后在 CSV 中发送shipment_type_namecountry_country_code属性。

你会做一些与其他关系类似的事情。