我正在使用roo-gem
导入以下设计的作者电子表格:
我在数据库中有名为 authors
,的表states
,publishers
并且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 模板中添加任何publisher
or时,该条目将被添加到表中,这是我不想要的。如果列出所有或来自应用程序,我会发现几个在导入期间创建的不应该存在的条目。excel 模板具有出版商和流派的下拉列表,就像它们出现在数据库中的相应表中一样。一种解决方案是锁定模板,但在目前的情况下这是不可能的。genre
publishers
genres
publishers
genres
我认为first_or_create
这是唯一会在找不到新记录的情况下添加新记录的方法,但似乎即使该first
方法在这里的行为也相同。
方法中是否有一些模型验证或调整可以防止未经授权publishers
和genres
被创建?
谢谢