嗨,这是我的第一篇文章。
我一直在尝试从 ruby on rails screen cast 396 importing csv and excel files 中调整一些代码。适应是我使用的是多对多模型,其中单词属于列表,因此我想连同文件详细信息一起传递一个 list_id。
我认为由于 WordImport 模型不是真正的模型,事情变得更加困难。
我已经尝试了各种排列,但已经恢复到“关闭”状态。我想我想知道这是否也是最好的方法。
谢谢
我的表格是:
<%= form_for @word_import do |f| %>
<% if @word_import.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(@word_import.errors.count, "error") %> prohibited this import from completing:</h2>
<ul>
<% @word_import.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<%= hidden_field_tag 'list_id', @list.id %>
<div class="field">
<%= f.file_field :file %>
</div>
<div class="buttons">
<%= f.submit "Import" %>
</div>
我的控制器:
class WordImportsController < ApplicationController
def new
@word_import = WordImport.new
end
def create
@word_import = WordImport.new(word_import_params)
if @word_import.save
redirect_to root_url, notice: "Imported words successfully."
else
render :new
end
end
def word_import_params
params.require(:word_import).permit(:file)
end
private
def correct_user
@list = current_user.lists.find_by_id(params[:list_id])
redirect_to root_url if @list.nil?
end
end
和型号:
class WordImport
include ActiveModel::Model
attr_accessor :file
def initialize(attributes = {})
attributes.each { |name, value| send("#{name}=", value) }
end
def persisted?
false
end
def save
if imported_words.map(&:valid?).all?
imported_words.each(&:save!)
true
else
imported_words.each_with_index do |product, index|
product.errors.full_messages.each do |message|
errors.add :base, "Row #{index+2}: #{message}"
end
end
false
end
end
def imported_words
@imported_words ||= load_imported_words
end
def load_imported_words
@list = List.find(4) ## Would like to pass in a value from the controller
spreadsheet = open_spreadsheet
header = spreadsheet.row(1)
(2..spreadsheet.last_row).map do |i|
row = Hash[[header, spreadsheet.row(i)].transpose]
@list.words.create(row.to_hash)
end
end
def open_spreadsheet
case File.extname(file.original_filename)
when ".ods" then Roo::OpenOffice.new(file.path, nil, :ignore)
when ".csv" then Roo::Csv.new(file.path, nil, :ignore)
when ".xls" then Roo::Excel.new(file.path, nil, :ignore)
when ".xlsx" then Roo::Excelx.new(file.path, nil, :ignore)
else
raise "Unknown file type: #{file.original_filename}"
end
end
end