0

我正在使用roo-gem导入以下设计的作者电子表格:

在此处输入图像描述 我在数据库中有名为 authors,的表statespublishers并且genres各个 excel 列中的数据映射到这些表。如您所见,第一行表头非常详细,因为上传数据到authors表中的用户不是很精通。因为这么长的表头名称无法映射到表中的关联列中,所以我在 excel 模板中包含了第二行,然后在Author模型中添加了方法,如下所示:

class Author < ApplicationRecord
  belongs_to :state
  belongs_to :genre
  belongs_to :publisher

#validations

validates :name,  presence: true
validates :national_id,  presence: true

  def to_s
    name
  end

  def home_state
    state.try(:name)
  end

  def home_state=(name)
    self.state = State.where(:name => name).first_or_create
  end

   def publisher_name
    publisher.try(:name)
  end

  def publisher_name=(name)
    self.publisher = Publisher.where(:name => name).first
  end

  def listed_genre
    genre.try(:name)
  end

  def listed_genre=(name)
    self.genre = Genre.where(:name => name).first
  end

end

这里是authors_import.rb

class AuthorsImport
  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_authors
    spreadsheet = open_spreadsheet
    spreadsheet.default_sheet = 'Worksheet'
    header = spreadsheet.row(2)
    #header = header[0..25]
    (3..spreadsheet.last_row).map do |i|
      row = Hash[[header, spreadsheet.row(i)].transpose]
      #author = Author.find_by_national_id(row["national_id"]) || Author.new
      author = Author.find_by(national_id: row["national_id"], state_id: row["home_state"]) || Author.new
      author.attributes = row.to_hash
      author
    end
  end

  def imported_authors
    @imported_authors ||= load_imported_authors
  end

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

end

这是我的问题:当用户在相应的or表中找不到的 excel 模板中添加任何publisheror时,该条目将被添加到表中,这是我不想要的。如果列出所有或来自应用程序,我会发现几个在导入期间创建的不应该存在的条目。excel 模板具有出版商和流派的下拉列表,就像它们出现在数据库中的相应表中一样。一种解决方案是锁定模板,但在目前的情况下这是不可能的。genrepublishersgenrespublishersgenres

我认为first_or_create这是唯一会在找不到新记录的情况下添加新记录的方法,但似乎即使该first方法在这里的行为也相同。

方法中是否有一些模型验证或调整可以防止未经授权publishersgenres被创建?

谢谢

4

0 回答 0