アップロードしたCSVを元データにテーブルを作る。
こんな要件があるのかわからないけどうちのシステムにはあったので。
アップロードしたCSVを前に使ったCSVパースライブラリを通して配列に突っ込み、
それをとりあえずテーブル化したrhtmlに渡してみた。
アップロードモデルの作り方次第で少しやり方が変わるかもしれないけど、
あくまでCSVの内容にモデルは触れないようにしている。ほんとはURLを突っ込む
予定なんだけどまだしてません。
元ファイルがパースエラー出した時にどうraiseさせるとか、そういったフォローも今
入れてません。このあたりはおいおい必要になるはず。
とりあえずuploadモデルを作成。create_uploads.rbにはURLと作成日付だけ用意
しておいた。今回は結局DB使ってないけど。
def self.up create_table :uploads do |t| t.column "filepath", :string, :null => false t.column "created_at", :datetime end end
アップロード先のディレクトリをpublic配下に用意。publicの外でもいけるかもしれないけど
その場合ディレクトリトラバーサルとかそのあたり注意なのかな。特に直接見られてどうと
いうことはないと思われるやり取りなのでpublic/filesを用意してそこに持っていくことにする。
uploadモデルのsaveメソッドをオーバーライドしてファイルの保管。
upload.rb
def self.save(file) File.open("public/files/#{file.original_filename}", "w"){ |f| f.write(file.read) } end def self.filepath(file) return "public/files/#{file.original_filename}" end
今回DBをやりとりせずにやるだけやっちゃう系でいってるのでfilepathをベタで返すメソッドを用意。saveの方はWindowsだとモードを"wb"にしないと壊れるらしい?
upload_controller.rbの作成。
require "NKF" require "CSV" class UploadController < ApplicationController def index render :action => 'upload_form' end def upload @filename = params[:upload][:file].original_filename if @filename != "" then if Upload.save(params[:upload][:file]) @uploads = parse_csv(Upload.filepath(params[:upload][:file])) else render :action => 'upload_form' end end end def upload_form end private def parse_csv(upfile) a = Array.new open("#{upfile}").each {|line| b = Array.new CSV.parse(line).each{|row| row.each{|item| b.push(NKF::nkf("-w", item.to_s)) } } a.push(b) } return a end end
CSV.parseで1行のarrayが作られるのでその要素を切り出してひとつひとつ変換。
このあたりもっときれいに書けそうな気がするけどどう手をつけるといいのかな。
余裕が出来たら調べないと…
裏方は大体こんな感じ。あとはフォームのrhtmlと結果表示のrhtml。
upload_form.rhtml
<html> <head> <title>ファイルアップロード</title> </head> <body> <h1>ファイルアップロードサンプル</h1> <% form_tag ({:action => 'upload'}, :multipart =>true) do %> ファイルを選んでください:<%= file_field "upload", 'file' %> <%= submit_tag "upload" %> <% end %> </body> </html>
upload.rhtml
<h1>Upload結果</h1> <table border="1"> <% for item in @uploads %> <tr> <% item.each{|column|%> <td><%=h column %></td> <%}%> </tr> <% end %> </table>
とりあえず全件表示って感じで。CSVでやりとりとか結構な分量になってるものが多い
のでこれそのまま使っていいかはなんとも。
一応こんな風にしてやってみたけどちゃんとした説明が出来るくらい理解しているかって
いうところもあるし見直していかないといけないなあ。もっとこうしろ的な指摘があればぜひ。