2016-11-13 29 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