2016-11-13 57 views
-1

我想上传一个excel文件到我的Rails 5应用程序。Rails 5 - 如何上传excel文件 - 教程不工作

我试过this教程,还有this一,this一。我无法让他们工作。

我叫一个命名空间中的模型:

class Randd::Field < ApplicationRecord 
require 'csv' 

我已经在我的模型尝试每一种方法:

def self.import(file) 
    CSV.foreach(file.path, headers: true) do | row | 
     Randd::Field.create! row.to_hash 
    end 
    end 

    def self.import(file) 
    CSV.foreach(file.path, headers: true) do |row| 

     randd_field_hash = row.to_hash # exclude the price field 
     randd_field = Randd::Field.where(id: randd_field_hash["id"]) 

     if randd_field.count == 1 
     randd_field.first.update_attributes(randd_field_hash) 
     else 
     Randd::Field.create!(product_hash) 
     end # end if !product.nil? 
    end # end CSV.foreach 
    end # end self.import(file) 

在我的控制,我有:

类的RandD: :FieldsController < ApplicationController

def index 
    @randd_fields = Randd::Field.all 
end 

def new 
    @field = Randd::Field.new 
end 

def import 
    Randd::Field.import(params[:file]) 
    redirect_to root_path, notice: "Data imported" 
end 

end 

控制器上的注意事项:

  1. 我没有任何强烈PARAMS - 这似乎很奇怪,我,但没有一个教程似乎表明他们是必需的。
  2. 我做了上面的新动作,因为我试图制作一个单独的表单来上传文件,而不是使用索引动作来保存文件。我已尝试使用新的以及使用教程中列出的表单字段在索引视图中列出的过程。这两种方法都无效。

在我的路线,我有:

namespace :randd do 
    resources :fields do 
     collection do 
     post :import 
     end 
    end 
    end 

在我的形式,我有:

<%= simple_form_for [:randd, @field], multipart: true do |f| %> 
     <div class="form-inputs"> 
      <%= f.file_field :file %> 
    </div> 

      <div class="form-actions"> 
      <%= f.button :submit %> 
      </div> 
    <% end %> 

当我尝试用新的观点来上传文件,我得到一个错误,说:

undefined method `randd_randd_fields_path' for #<#<Class:0x007fd5edf73738>:0x007fd5f698f430> 
Did you mean? randd_fields_path 

,当我尝试使用索引视图来保存表单字段,我有:

<%= form_tag import_randd_fields_path, multipart: true do |f| %> 
       <%= f.file_field :file %> 
      <%= submit_tag 'Import' %> 
<% end %> 

当我尝试使用索引视图上传的文件,我得到一个错误,指出:

undefined method `file_field' for nil:NilClass 

谁能推荐另一教程如何上传excel文件到轨道5.我可能使用的是太旧 - 但我找不到更好的帮助来源。

下一次尝试

我设法呈现与下面的建议的形式:

<%= simple_form_for (@field), multipart: true do |f| %> 

我必须定义节目,为了让这个过程创造我的田地控制器动作跑。我加入到我的RandD域控制器,所以它现在有:

class Randd::FieldsController < ApplicationController 

def index 
    @randd_fields = Randd::Field.all 
end 

def new 
    @field = Randd::Field.new 
end 

def create 
    redirect_to action: "import" 
end 

def show 
    redirect_to action: "index" 
end 


def import 
    Randd::Field.import(params[:file]) 
    redirect_to action: "index", notice: "Data imported" 
end 

end 

当我经历的过程,上传文件并提交,我可以在日志中看到这种情况出现:

Started GET "/images/upload/cache/presign?extension=.xls&_=142388" for ::1 at 2016-11-14 10:50:12 +1100 
Started POST "/randd/fields" for ::1 at 2016-11-14 10:50:12 +1100 
Processing by Randd::FieldsController#create as JS 
    Parameters: {"utf8"=>"✓", "authenticity_token"=>"8vJ7bA==", "randd_field"=>{"file"=>"{\"id\":\"04f4e0679f2a562.xls\",\"storage\":\"cache\",\"metadata\":{\"size\":165376,\"filename\":\"FOR codes.xls\",\"mime_type\":\"\"}}"}} 
Redirected to http://localhost:3000/randd/fields/import 
Completed 200 OK in 43ms (ActiveRecord: 0.0ms) 


Started POST "/randd/fields" for ::1 at 2016-11-14 10:50:13 +1100 
Processing by Randd::FieldsController#create as HTML 
    Parameters: {"utf8"=>"✓", "authenticity_token"=>"8v+bbA==", "commit"=>"Create Field"} 
Redirected to http://localhost:3000/randd/fields/import 
Completed 302 Found in 40ms (ActiveRecord: 0.0ms) 


Started GET "/randd/fields/import" for ::1 at 2016-11-14 10:50:13 +1100 
Processing by Randd::FieldsController#show as HTML 
    Parameters: {"id"=>"import"} 
Redirected to http://localhost:3000/randd/fields 
Completed 302 Found in 29ms (ActiveRecord: 0.0ms) 


Started GET "/randd/fields/import" for ::1 at 2016-11-14 10:50:13 +1100 
Started GET "/randd/fields" for ::1 at 2016-11-14 10:50:13 +1100 
Processing by Randd::FieldsController#show as HTML 
    Parameters: {"id"=>"import"} 
Redirected to http://localhost:3000/randd/fields 
Completed 302 Found in 32ms (ActiveRecord: 0.0ms) 


Processing by Randd::FieldsController#index as HTML 
    Rendering randd/fields/index.html.erb within layouts/application 
    Randd::Field Load (1.6ms) SELECT "randd_fields".* FROM "randd_fields" 
    Rendered randd/fields/index.html.erb within layouts/application (46.9ms) 
    User Load (1.8ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT $2 [["id", 4], ["LIMIT", 1]] 
    Setting Load (1.0ms) SELECT "settings".* FROM "settings" WHERE "settings"."user_id" = $1 LIMIT $2 [["user_id", 4], ["LIMIT", 1]] 
    Rendered layouts/nav/_inner.html.erb (93.3ms) 
Completed 200 OK in 2773ms (Views: 2732.5ms | ActiveRecord: 4.4ms) 


Started GET "/randd/fields" for ::1 at 2016-11-14 10:50:16 +1100 
Processing by Randd::FieldsController#index as HTML 
    Rendering randd/fields/index.html.erb within layouts/application 
    Randd::Field Load (0.9ms) SELECT "randd_fields".* FROM "randd_fields" 

但是 - - 这不起作用,因为表格是空的。它没有实例。

COURT3NAY的建议

的建议是我在交换领域控制器导入操作来创建操作的内容。我现在控制器有:

class Randd::FieldsController < ApplicationController 

def index 
    @randd_fields = Randd::Field.all 
end 

def new 
    @field = Randd::Field.new 
end 

def create 
    Randd::Field.import(params[:file]) 
    redirect_to action: "index", notice: "Data imported" 
    # @field = Randd::Field.new(randd_field_params) 
    # redirect_to action: "import" 
end 

def show 
    redirect_to action: "index" 
end 


# def import 
# # byebug 
# Randd::Field.import(params[:file]) 
# redirect_to action: "index", notice: "Data imported" 
# end 

private 
def randd_field_params 
    params.fetch(:randd_field, {}).permit(:title, :anz_reference) 
end 

end 

我的形式现在有(我删除了进口URL路径):

<%= simple_form_for (@field), multipart: true do |f| %> 
    <%= f.error_notification %> 

    <div class="form-inputs" style="margin-bottom: 50px"> 
    <div class="row"> 
     <div class="col-md-12"> 
     <div class="form_title">Research Field Codes</div> 
     </div> 
    </div> 

    <div class="row"> 
     <div class="col-md-12"> 
     <%= f.file_field :file %> 
     </div> 
    </div> 
    </div> 

    <div class="row"> 
    <div class="col-md-10 col-md-offset-1" style="margin-top: 50px"> 
     <div class="form-actions"> 
     <%= f.button :submit %> 
     </div> 
    </div> 
    </div> 
<% end %> 

错误现在说:

The action 'import' could not be found for Randd::FieldsController 

错误消息突出问题用我自己写的代码。

def process(action, *args) 
     @_action_name = action.to_s 
     unless action_name = _find_action_name(@_action_name) 
     raise ActionNotFound, "The action '#{action}' could not be found for #{self.class.name}" 
     end 

我认为它是一个问题,但因为我没有一个导入动作了。我应该创建一个以前导入的东西(根据教程)。

我的猜测在获得解决此:

我寻找,我仍然要求“进口”。我在两个地方使用它,所以我尝试在两者中交换“导入”以创建。现在

,我的模型有:

def self.create(file) 
    CSV.foreach(file.path, headers: true) do |row| 

     randd_field_hash = row.to_hash # exclude the price field 
     randd_field = Randd::Field.where(id: randd_field_hash["id"]) 

     if randd_field.count == 1 
     randd_field.first.update_attributes(randd_field_hash) 
     else 
     Randd::Field.create! row.to_hash#(randd_field_hash) 
     end # end if !product.nil? 
    end # end CSV.foreach 
    end # end self.import(file) 

的创建操作在我的控制器有:

def create 
    Randd::Field.create(params[:file]) 
    redirect_to action: "index", notice: "Data imported" 
    # @field = Randd::Field.new(randd_field_params) 
    # redirect_to action: "import" 
end 

这个猜测犯规解决任何问题,但。我仍然收到一条错误消息:

undefined method `path' for nil:NilClass 

我也不知道这是什么意思。

+0

你试过了吗?<%= simple_form_for @field,multipart:true do | f | %>' – court3nay

+0

是的 - 它加载表单,但它不工作与导入的数据创建记录 – Mel

回答

0

你真的很接近。 您需要发布才能导入。你刚开场#显示

Processing by Randd::FieldsController#show as HTML 
Parameters: {"id"=>"import"} 

您需要发布到域#导入

<%= simple_form_for (@field), url: import_fields_path, multipart: true do |f| %> 

,或者只是使用#创建的,而不是重定向领域。一旦你发布到#create重定向将失去参数。

+0

错误现在说:未定义的方法'路径'为零:NilClass。它突出显示了这一行:def self.import(file) CSV.foreach(file。路径,标题:true)do | row | – Mel

+0

我假设CSV在某种程度上是xls的代名词。这可能是我的问题吗?也许我会按照说明使用Excel电子表格不起作用的东西。 – Mel

+0

不,它意味着你的字段(params [:file])是空的。阅读错误 - 未定义的方法路径为零。你正在调用file.path,因此,文件是零。跟踪它 - 你调用Radd :: Field.import(params [:file]),所以params [:file]是零。所以你的表单发布nil params [:file]。为什么? – court3nay