0

嗨,这是我的第一篇文章。

我一直在尝试从 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
4

1 回答 1

0

解决方案很简单,尽管我不确定它是否是最好的做事方式。

我在名为 :list_id 的 WordImport ActiveModel::Model 中创建了一个 att_assessor 并将 list_id 传递给它。然后在 WordImport 中找到列表并将其分配给实例变量。

于 2013-11-03T00:05:53.723 回答