Scaffoldの生成したコードの説明
Sacffoldが生成したコードは標準的なRuby on Railsのコードですので、これを理解する事は Ruby on Railsの理解につながります。今回はページ数の都合もあり、事細かな説明はできませんので適宜Ruby言語リファレンスマニュアルとRuby on RailsのAPIリファレンスを参照してください。
Ruby on RailsはMVCモデルのフレームワークなので Model、View、Controllerの順に解説します。
Model(モデル)
Modelのファイルは app/mode/player.rb ファイルです。
class Player < ActiveRecord::Base end
PlayerクラスはActiveRecord::BaseというO/Rマッパーを継承したクラスとして定義されています。通常はここにロジックやテーブルの関連、バリデーション(データのエラーチェック)などを記述します。
ActiveRecordは、O/Rマッパーとしてかなり豊富な機能を持っています。
View(ビュー)
Ruby on Railsは View には標準では ERB というテンプレートエンジンを使っています。ERBにはJSP等と同じように HTML の中に <% ~ %>で括られた Rubyの文や <%= ~ %> で括られた Ruby の式を記述していきます。
一覧表示のViewは app/view/players/index.html.erb ファイルです。
<h1>Listing players</h1> <table> <tr> <th>Name</th> <th>Team</th> <th>No</th> <th>Goal</th> <th>Assist</th> </tr> <% @players.each do |player| %> <tr> <td><%=h player.name %></td> <td><%=h player.team %></td> <td><%=h player.no %></td> <td><%=h player.goal %></td> <td><%=h player.assist %></td> <td><%= link_to 'Show', player %></td> <td><%= link_to 'Edit', edit_player_path(player) %></td> <td><%= link_to 'Destroy', player, :confirm => 'Are you sure?', :method => :delete %></td> </tr> <% end %> </table> <br /> <%= link_to 'New player', new_player_path %>
ここでは、<% @players.each do |player| %> でインスタンス変数 @players(配列です)の要素を1つづつ取り出し player変数に代入し、 <% end %> までの間をくり返ことで選手の成績のテーブルが作られます。
<%=h player.name %> について、もう少し細かく解説すると「 <%= h(player.name()) %>で playerに代入されているオブジェクトのnameメソッドを呼び出し、結果の文字列をhメソッドでサニタイズ(< を >に置き換えるような処理)した文字列をHTMLに埋め込む」という処理を行っている、ということになります。結局、選手の名前が <td>と</td> の間に入ります。
リンク(<a href=...>タグ)は、link_to のような Rails(ActiveView)のメソッドで作成します。リンク以外にも <form ...>や <input...>のようにプログラムと関連するようなタグはActiveViewのメソッドで作成します。
上のテンプレートにはDOTYPEや<html>タグがありませんね。なぜでしょうか? 実はHTMLの作成時に下に示したレイアウトファイル app/view/layout/players.html.erb が使われているからです。
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> <head> <meta http-equiv="content-type" content="text/html;charset=UTF-8" /> <title>Players: <%= controller.action_name %></title> <%= stylesheet_link_tag 'scaffold' %> </head> <body> <p style="color: green"><%= flash[:notice] %></p> <%= yield %> </body> </html>
レイアウトファイルは、共通のヘッダーやフッターなどのHTMLを記述します。<%= yield %> の部分に各テンプレートから作られた文字列が取り込まれ、最終的なHTMLが作られます。
Controller(コントローラー)
Webアプリの処理をまとめるControllerは app/controllers/players_controller.rbファイルです。長いので分けて説明します。
a. 一覧表示
class PlayersController < ApplicationController def index @players = Player.all respond_to do |format| format.html # index.html.erb format.xml { render :xml => @players } end end
一覧表示は index メソッドで行います。 最初の行は ModelのPlayerクラスの all メソッド呼び出して、@playersに代入しています。 all メソッドは ActiveRecordのクラスメソッドでplayersテーブルの全レコードをPlayerオブジェクトの配列で戻します。また Viewに渡す値はインスタンス変数を使うので @playersというインスタンス変数に代入しています。
その下の respond_to から始まる部分を注目してください。Ruby on Railsは http://localhost:3000/plyaersやhttp://localhost:3000/plyaers.html リクエストに対してはHTMLを戻しますが、http://localhost:3000/plyaers.xml リクエストに対しては結果をXMLで戻します。Curlなどのようなリッチクライアント用のサーバーやWeb APIの場合は、XMLやJSONでデータを渡した方が便利ですが、Ruby on Rails はこの機能を最初から内蔵しているのです。
HTMLのリクエストの場合、indexメソッドの実行後は index.html.erbをテンプレートしとて使い、HTMLを出力します。
b. 詳細表示
def show @player = Player.find(params[:id]) respond_to do |format| format.html # show.html.erb format.xml { render :xml => @player } end end
詳細表示は show メソッドで行います。 params[]はパラメータの入っているHashです。 http://localhost:3000/players/9 というリクエストがあった場合、 params[:id]には id番号が 9 が入ります。
Player.find(9)はplayersテーブルのid=9のレコードを取得するメソッドです。 respond_to 以降は indexメソッドと同じですね。HTMLのリクエストの場合、showメソッド実行後は show.html.erbをテンプレートしとて使いHTMLを出力します。
c. 新規作成
def new @player = Player.new respond_to do |format| format.html # new.html.erb format.xml { render :xml => @player } end end def create @player = Player.new(params[:player]) respond_to do |format| if @player.save flash[:notice] = 'Player was successfully created.' format.html { redirect_to(@player) } format.xml { render :xml => @player, :status => :created, :location => @player } else format.html { render :action => "new" } format.xml { render :xml => @player.errors, :status => :unprocessable_entity } end end end
新規作成画面の表示はnewメソッドで、新規登録フォームからのPOSTデータの受付は createメソッドで行います。ここではHTMLリクエストに対する動作のみ説明します。
newメソッドは新規登録フォーム(new.html.erb)用に空のPlayerオブジェクトを作成し、new.html.erbをテンプレートとして使いHTMLを出力します。
createメソッドですが、params[:player]にはPlayerのフィールドに対応するデータがHashで入ります(例 {"name"=>"YULE,Chris", "goal"=>"19", "no"=>"75", "assist"=>"25", "team"=>"NPC"})。このデータでPlayerオブジェクトを生成し、saveメソッドでDBの格納します。
格納が成功した場合は saveメソッドは true を戻しますので、redirect_to(@player)で作成されたデータの詳細表示画面にリダイレクトします。その際、flash[:notce] に書かれたメッセージが表示されます。flashは次のページまで有効な特別なセッションです。
格納が失敗した場合は render で newメソッド用のテンプレートを指定していますので new.html.erb画面が表示されます。
ここまでのまとめ
- Ruby on Railsではクラス名やメソッド名、テーブル名などが規約に則って決まっているので設定ファイル等を書かずに済みます。これは CoC(Convention Over Configuration)と呼ばれています。
- サーバーを起動したウィンドウにはログが表示されるので、それを見ることでRuby on Railsの動作を理解する助けになります。
- Ruby on Railsの構成要素は比較的シンプルな構造で Java等のフレームワークを使った事のある人であれば比較的理解しやすいと思います。