Ruby on Railsを使ってファイルのアップロードシステムを作ってみる

Ruby on Railsをいじりはじめてから1ヶ月くらい経つ。Ruby on Railsを使った開発スタイルというのがまだよくわかっていないけれども、次のようなポイントはわかってきた。

MVCモデルが基本となって、Webアプリケーションが構成される
・Modelにはデータ構造やデータ処理などを記述
・Viewには実際のHTMLに相当するような処理を記述
・Controllerにはサーバーサイド処理を記述
・Action名とViewに作るrhtmlファイルを同じ名前にする

などなど。MVCモデルを理解するのにちょっと苦労をしたのだけども、すごい先生のレッスンで一気にステップアップができた。Mash up Awardで知り合ったジュンヤさんと先日別件でSkypeチャットをしていたときにちょっと教えてもらっちゃったのだ。
えへ、得した。
ジュンヤさんは、つくるぶのサイトでRuby on Railsの解説などをしているくらいの人なので、ある意味、直接教えてもらえるなんてありえない出来事だ。エディゲレロが突然急死してしまうくらいありえない出来事だ(ゲレロの死はいまでも信じられない)。
しかもちょっと教えてくれるというレベルではなく、何がなぜ理解できないのかというところから始まって、なぜそのような仕組みになっているのかをとても丁寧に教えてもらっちゃったのだ。

その恩返しではないけれども、RORをどんどん触っていこうと思う。
親というのは子供の成長を見るのが一番楽しいはず。師匠は弟子の成長が喜びのはず。勝手にジュンヤさんをロールモデルにしていきますよ〜。けもののみちも一歩からとういことで、大胆に身の程も考えずに、どんどん作っては公開、作っては公開していこうと思う。ジュンヤさんも1月1サービス公開ってやってたし(過去形)。


今回Tipsとして選んだのはファイルのアップロードだ。


写真とかをアップロードしてホゲホゲするようなWebアプリケーションって世の中にたくさんある。このアップロードという処理はたぶんWebアプリケーションの中では基本の基本だろう。なので今回はCSVファイルをアップロードできるアプリケーションを作ってみようと思う。

参考にしたサイトはこちら。


1.まずはプロジェクトを作成する。

rails uploader #uploaderがプロジェクト名


2.つぎにControllerを作る。

ruby script/generate controller uploader #さっき作ったプロジェクトに移動してから


3.するとcontrollersフォルダにuploader_controller.rbファイルができている。これにActionを追加する。特に意味もないけどAction名もuploaderでいいかな。

def uploader
end

特に処理はなし。


4.次にuploader.rhtmlファイルをviews/uploaderフォルダに作成して、実際にWebブラウザに表示されるHTML部分を記述する。
今回はファイルを参照ボタンで読み込んでファイルパスをテキストボックスに入力し、送信ボタンでファイルをアップロードするというインターフェースが必要になってくる。

<form action="create" method="post" enctype="multipart/form-data">#<は全角で記述してます
<b>CSV file:</b><br />
<%= file_field "file", "csv", "size" => 60 %>
<p><input type="submit" value="upload" />

</form>

おっそろしいことにこの<%= file_field "file", "csv", "size" => 60 %>だけでファイルパスを入力するテキストボックスと参照ボタンを自動生成してくれる。fileがIDで、csvが属性項目になるのかな?あとでファイルのパスを読み込むときに利用する。またenctype="multipart/form-data"となっているところは、とりあえずこういうものだと理解(あとで勉強する)。


5.ファイルを保存するためのAction追加
1行目のaction="create"となっている部分が、controllerのAction名と連携しているので、同じ名前のActionをuploader_controller.rbファイルに作成する。

def create
@filename = params[:file]['csv'].original_filename
if @filename != "" then
File.open("public/images/#{@filename}", "wb"){ |f| f.write(params[:file]['csv'].read) }
session[:filename] = "/images/#{@filename}"
end
redirect_to :action => 'list'
end

rhtmlで記述したフォームの定義によって、params[:file]['csv'].original_filenameここにファイル名があり、params[:file]['csv'].readこの記述でファイルデータを読み込めるようだ。
とりあえずimagesフォルダに格納しよう(フォルダ指定などは次回)。

でこの保存処理ができたら、結果を表示させるようにredirect_to :action => 'list'と記述して、listアクションも追加する。
session[:filename] = "/images/#{@filename}"は何をしているかというと、ページ遷移したあとでも変数の値を利用したい場合に利用できるsessionを使ってファイル名を保存しているのだ。


6.最後にlist.rhtmlを作成する。アップロードされたファイル名を表示させたいので、list.rhtmlには

<%= session[:filename]%>

とだけ記述する。

listアクションは何も書かない。

def list
end


これで完成!

ruby script/server

でWEBBrickを起動して、Webアプリケーションにアクセス。
http://localhost:3000/uploader/uploader


で、できてしまった・・・。わーいわーい。こんな風に結構フィーリングでえいや!とできてしまうところがRuby on Railsのすごいところなのかな。西原理恵子も「まあじゃんほうろうき」で「符計算はフィーリングよ」と豪語していたけども、それだな。

Ruby on Railsはフィーリングで何とかなる

寝不足の状態で今が昼なのか夜なのかもわからない人でも、アルコール飲みながら妙なテンションで笑っている人も、フィーリングさえ合えば、きっとRuby on Railsはあなたの強い味方です!
といってもRuby on Railsだからっぽい処理ってまだでてきてないか(笑)信じないように(笑)

今回はまったところは
session[:filename] = "/images/#{@filename}"
これ・・・この=のあとを"/images/" + @filenameと書くとエラーになってしまった。なぜエラーになるのか結局わからず記述方法を変えまくってようやく完成。今度先生に聞いてみようっと。