說明:
我們想要在records底下新建一個頁面([project path]/records/import/),在這個頁面使用者可以選擇想要上傳的local端檔案,然後按下import按鈕匯入資料。
首先是要處理當使用者輸入網址/import/時,由show action 處理,並 render import.html.erb
app/controller/records_controller.rb
def show
if valid_page?
render params[:id]
else
render file:"public/404.html", status: :not_found
end
end
在指定的頁面 (在這裡是import.html.erb)中加入可以上傳檔案的html
<h1>import csv file</h1>
<%= form_tag import_records_path, multipart: true do %>
<%= file_field_tag :file %>
<%= submit_tag "Import CSV" %>
<% end %>
目前為止rails 還不知道import_records_path會回傳什麼path,所以需要在config/routes中定義:
resources :records do
collection{post:import}
end
接下來當在index.html.erb頁面,使用者選擇本機端的特定檔案後,按下Import CSV 按扭,router會導引到records/import/ 這個path(並將特定 檔案的path存到變數:file),而當rails接收到records/import這個path ,會去執行records controller底下的#import action。
於是我們要定義import action. edit app/controller/record_controller.rb
def import
Record.import(params[:file])
end
我們希望使用import這個method來將資料匯入,目前為止還沒有定義這個method,而這個method是Record Object底下的方法,所以我們接下來要定義他
app/models/record.rb
require 'csv'
def self.import(file)
CSV.foreach(file.path, headers: true) do |row|
record_hash = row.to_hash #把csv檔的以列(row)為單位pop-out
record = Record.where(id: record_hash["id"])
if record.count == 1
record.first.update_attributes(record_hash)
else
Record.create!(record_hash)
end # end if !record.nil?
end # end CSV.foreach
end # end self.import(file)
這段程式會把csv檔的第一行作為index,存到record_hash這個變數中,找到指定的欄位
當原始資料庫中沒有值時,會初始之,若已經有資料了,就加上去。
example.csv
program_id,distance,property_id,minutes,seconds,user_id,owner_id,month,date,year
1,1,1,2,2,1,1,3,22,2016
1,1,1,2,2,1,1,3,22,2015
1,1,1,2,2,1,1,3,22,2014
圖一:加入上傳資料功能後的頁面
圖二:選擇檔案後,會在頁面上顯示路徑
圖三:資料成功加入資料庫
延伸應用:可應用於使用者上傳檔案,運算後輸出