ActiveRecord::AssociationTypeMitch Rails CSV导入

ActiveRecord::AssociationTypeMitch Rails CSV导入,csv,ruby-on-rails-5,roo,Csv,Ruby On Rails 5,Roo,我正在使用gemroo导入CSV数据。它工作得很顺利,直到有关联为止,我希望roo可以将字符串转换为关联中相应的整数值。在我的例子中,我有一个Staff模型,它属于状态 class State < ApplicationRecord has_many :staffs end 突出显示的来源是: staff.attributes = row.to_hash gemroo是否可以将csv文件中的“Texas”翻译为(比如)id 2,而不是最终用户在上传数据之前进行大量翻译工作 这

我正在使用
gemroo
导入CSV数据。它工作得很顺利,直到有关联为止,我希望roo可以将字符串转换为关联中相应的整数值。在我的例子中,我有一个
Staff
模型,它属于
状态

class State < ApplicationRecord
    has_many :staffs

end
突出显示的来源是:

staff.attributes = row.to_hash
gemroo
是否可以将csv文件中的“Texas”翻译为(比如)id 2,而不是最终用户在上传数据之前进行大量翻译工作

这里是
staff\u imports.rb

class StaffsImport
  include ActiveModel::Model
  require 'roo'

  attr_accessor :file

  def initialize(attributes={})
    attributes.each { |name, value| send("#{name}=", value) }
  end

  def persisted?
    false
  end

  def open_spreadsheet
    case File.extname(file.original_filename)
    when ".csv" then Csv.new(file.path, nil, :ignore)
    when ".xls" then Roo::Excel.new(file.path, nil, :ignore)
    when ".xlsx" then Roo::Excelx.new(file.path)
    else raise "Unknown file type: #{file.original_filename}"
    end
  end

  def load_imported_staffs
    spreadsheet = open_spreadsheet
    header = spreadsheet.row(1)
    (2..spreadsheet.last_row).map do |i|
      row = Hash[[header, spreadsheet.row(i)].transpose]
      staff = Staff.find_by_national_id(row["national_id"]) || Staff.new
      staff.attributes = row.to_hash
      staff
    end
  end

  def imported_staffs
    @imported_staffs ||= load_imported_staffs
  end

  def save
    if imported_staffs.map(&:valid?).all?
      imported_staffs.each(&:save!)
      true
    else
      imported_staffs.each_with_index do |staff, index|
        staff.errors.full_messages.each do |msg|
          errors.add :base, "Row #{index + 6}: #{msg}"
        end
      end
      false
    end
  end

end
最后,
staff\u导入控制器.rb

class StaffsImportsController < ApplicationController

  def new
    @staffs_import = StaffsImport.new
  end

  def create
    @staffs_import = StaffsImport.new(params[:staffs_import])
    if @staffs_import.save
      flash[:success] = "You have successfully uploaded your staff!"
      redirect_to staffs_path
    else
      render :new
    end
  end
end
class StaffsImportsController

非常感谢您提供的任何帮助/线索。

由于这里提供了非常详细的问题和非常好的答案,我设法找到了解决方案

class StaffsImport
  include ActiveModel::Model
  require 'roo'

  attr_accessor :file

  def initialize(attributes={})
    attributes.each { |name, value| send("#{name}=", value) }
  end

  def persisted?
    false
  end

  def open_spreadsheet
    case File.extname(file.original_filename)
    when ".csv" then Csv.new(file.path, nil, :ignore)
    when ".xls" then Roo::Excel.new(file.path, nil, :ignore)
    when ".xlsx" then Roo::Excelx.new(file.path)
    else raise "Unknown file type: #{file.original_filename}"
    end
  end

  def load_imported_staffs
    spreadsheet = open_spreadsheet
    header = spreadsheet.row(1)
    (2..spreadsheet.last_row).map do |i|
      row = Hash[[header, spreadsheet.row(i)].transpose]
      staff = Staff.find_by_national_id(row["national_id"]) || Staff.new
      staff.attributes = row.to_hash
      staff
    end
  end

  def imported_staffs
    @imported_staffs ||= load_imported_staffs
  end

  def save
    if imported_staffs.map(&:valid?).all?
      imported_staffs.each(&:save!)
      true
    else
      imported_staffs.each_with_index do |staff, index|
        staff.errors.full_messages.each do |msg|
          errors.add :base, "Row #{index + 6}: #{msg}"
        end
      end
      false
    end
  end

end
class StaffsImportsController < ApplicationController

  def new
    @staffs_import = StaffsImport.new
  end

  def create
    @staffs_import = StaffsImport.new(params[:staffs_import])
    if @staffs_import.save
      flash[:success] = "You have successfully uploaded your staff!"
      redirect_to staffs_path
    else
      render :new
    end
  end
end