何を作っていたかについて復習しておきましょう。
「スタート」を押す→処理がはじまる→処理の進捗状況がグラフ表示される
という感じのものを作っている途中でした。
そして、構成要素に分けると、
- 1から100までを一秒に1ずつカウントアップするworker
- そのworkerをキックするページA
- そのworkerの進捗状況をJSONかRJSで返すページB
- Bを定期的に呼び出し進捗グラフを表示するAjaxなページC
となるのでした。
前回は、
1から100までを一秒に1ずつカウントアップするworkerまで作ったのでしたね。
さっそく続きをはじめましょう。
ここまでRailsのサーバーを起動していませんでしたので、Railsのサーバーの起動について念のため触れておきますね。
Railsのサーバーの起動は、script/serverを利用します。(RAILSROOT)で、以下のようにします。
$ ./script/server => Booting Mongrel (use 'script/server webrick' to force WEBrick) => Rails application starting on http://0.0.0.0:3000 => Call with -d to detach => Ctrl-C to shutdown server ** Starting Mongrel listening at 0.0.0.0:3000 ** Starting Rails with development environment... ** Rails loaded. ** Loading any Rails specific GemPlugins ** Signals ready. TERM => stop. USR2 => restart. INT => stop (no restart). ** Rails signals registered. HUP => reload (without restart). It might not work well. ** Mongrel 1.1.3 available at 0.0.0.0:3000 ** Use CTRL-C to stop.
上記の状態で、http://localhost:3000/でRailsにアクセスすることができます。
次に、レイアウトを設置しましょう。
レイアウトは、各ページに共通の要素をまとめて定義するための機能です。必須ではありませんが、HTMLを書く量が減るので、原稿の都合上利用させていただきます(笑)
以下の内容を、(RAILSROOT)/app/views/layouts/application.html.erbとして保存してください。
<html> <head> <title>brdbtest1</title> <%= javascript_include_tag :defaults %> </head> <body> <%= yield %> </body> </html> </pre></div>
そのworkerをキックするページA
「スタート」をクリック→workerメソッドcount_upが起動する
というような流れを実装しましょう。
controllerの名前はcountupとします。
$ ./script/generate controller countup index exists app/controllers/ exists app/helpers/ create app/views/countup exists test/functional/ create app/controllers/countup_controller.rb create test/functional/countup_controller_test.rb create app/helpers/countup_helper.rb create app/views/countup/index.html.erb
この時点で、http://localhost:3000/countup/を見に行くと、以下のような画面が表示されるはずです。
まず「『スタート』をクリック」の部分を用意します。せっかくなのでRailsのAjax機能を使ってみましょう。
app/views/countup/index.html.erbを以下のようにしましょう。
<%= link_to_remote "Start", :url => { :action => 'start' } %>
次に「workerメソッドcount_upが起動する」に相当するアクション「start」を用意します。
app/controllers/countup_controller.rbを以下のようにしましょう。
class CountupController < ApplicationController def index end def start MiddleMan.ask_work(:worker => :foo_worker, :worker_method => :count_up) render :update do |page| page.alert "Asked worker to count up" end end end
MiddleMan.ask_workは、前回見た書式そのものですね。FooWorkerにcount_upメソッドを実行するようにお願いするメソッドでした。
本題から少し逸れますが、render :update以下は、元のページにJavaScriptアラートで反応を返すことを目的とした記述です。このstartアクションは、link_to_remoteタグによって、ブラウザからはxmlHttpRequestで呼び出されています。render :updateを使うことで、ブラウザには以下のような応答が返ります。Content-Type: text/javascriptだからJavaScriptとして実行されるという仕組みですね。
HTTP/1.1 200 OK Connection: close Date: Thu, 21 Feb 2008 05:29:21 GMT Set-Cookie: _bdrbtest1_session=BAh7BiIKZmxhc2hJQzonQWN0aW9uQ29udHJvbGxlcjo6Rmxhc2g6OkZsYXNo%250ASGFzaHsABjoKQHVzZWR7AA%253D%253D--595f473532320fd4d049e91c14229afbcee7892d; path=/ Status: 200 OK X-Runtime: 0.01252 ETag: "71d00b270c71787898354c71bfe1243a" Cache-Control: private, max-age=0, must-revalidate Server: Mongrel 1.1.3 Content-Type: text/javascript; charset=utf-8 Content-Length: 151 try { alert("Asked worker to count up"); } catch (e) { alert('RJS error:\n\n' + e.toString()); alert('alert(\"Asked worker to count up\");'); throw e }Connection closed by foreign host.
こうした書式をRJS (Ruby-generated JavaScript)というそうです。これでJavaScriptを一行も書かずに済む...!ということには決してなりませんが、一部簡単に書くことはできそうですね。
さて、早速実際に見てみましょう。
http://localhost:3000/countup/を開くと、以下のような画面になっているはずです。
"Start"をクリックすると、以下のようなJavaScriptアラートが上がります。
FooWorkerにはask_workしたきり、結果を何も表示していないので、ブラウザには何も出ていませんが、うまくいっていればこの時点でcount_upがはじまっているはずです。
さっそくscript/console経由で見てみましょう。
$ ./script/console Loading development environment (Rails 2.0.2) >> MiddleMan.ask_status(:worker => :foo_worker) => 6 >> MiddleMan.ask_status(:worker => :foo_worker) => 7 >> MiddleMan.ask_status(:worker => :foo_worker) => 8
無事にworkerメソッドが呼ばれ、カウントアップされているのがわかると思います。
後はこのカウントアップから進捗グラフを作るだけですね。
では続きは次回!
Leave a comment