はじめに
第11回 は自由で素直なフレームワーク「Ramaze 」の特徴について紹介しました。今回は、実際にRamazeでアプリケーションを作ってみます。
プロジェクトの始め方
まず、Ramazeでは「ramaze create 」でひな形を作る方法と、全てを自分で書いていく方法があるのでした。どちらを選んでも構いませんが、最初はひな形を使わず、1ファイルから少しずつ書いていくことをおすすめします。ramaze createを使うとたくさんのファイルが生成されるため、どれが何なのか分からなくなりがちです。
自動生成を使うのは、Ramazeにある程度慣れて、ディレクトリ構成などが分かってきてからで良いでしょう。今回も、自動生成は使わず、必要なファイルだけを用意することにしました。
ソースコード
今回は、英単語を登録したり、ランダムに一つ表示したりできる単語帳アプリケーションを作ってみました。github にてソースコードの全文を公開しています。といっても、HTMLを入れても100行程度しかないので、読むのに時間はかからないと思います。ファイル構成は以下のようになっています。
app.rb
アプリケーションの本体(64行) 。
view/index.html.erb
単語一覧画面のHTML(13行) 。
view/new.html.erb
単語追加画面のHTML(9行) 。
view/show.html.erb
単語表示画面のHTML(19行) 。
layout/default.html.erb|
HTMLのレイアウトの定義(15行) 。
public/
スタイルシートとJavaScript。
app.rbを実行するとサーバが起動するので、http://localhost:7999/ にアクセスしてください。動作例は以下のようになります。
図1 今回制作する、単語帳アプリケーション
モデル
Ramazeはいろいろな部分が「選択可能」になっているフレームワークでした。今回はDataMapper をモデル用のライブラリとして使うことにしました。app.rbの中から、モデルを定義している部分を見てみましょう。
リスト1 DataMapperによるモデル定義の例(app.rb)
DataMapper.setup(:default, "sqlite3://#{__DIR__('words.db')}")
class Word
include DataMapper::Resource
property :id, Serial
property :name, String
property :description, Text
validates_is_unique :name
end
DataMapper.auto_upgrade!
まずDataMapper.setupでデータベースに接続します。「 __DIR__」はRamazeの提供する便利なメソッドで、現在のファイル(ここではapp.rb)のあるディレクトリを起点としたパス名を返してくれます。
次に、単語帳の単語を表すモデルクラスWordを定義しています。DataMapperでは、継承ではなくMixinでモデルクラスを定義します。 DataMapper::ResourceをMixinすると、「 Text」や「Serial」といった定数が参照できるようになり、これを使ってプロパティの型を指定します(モデルクラスに直接プロパティの情報を書くのもDataMapperの特徴です) 。
最後に「DataMapper.auto_upgrade!」テーブルを作成しています。auto_upgrade!は、モデルクラスの構造からテーブルを自動生成するDataMapperのメソッドです。
ビュー
Ramazeではテンプレートエンジンもさまざまなものを選ぶことができます。今回は、RailsでおなじみのERBを使うことにします。テンプレートエンジンの指定は、コントローラクラスに「engine :ERB」等と書くことで行います。テンプレートファイルはview/以下に設置します(このディレクトリは設定で変更可能です) 。
レイアウト
Rails同様、HTMLの共通部分を「レイアウト」としてまとめて定義することができます。レイアウトファイルはlayout/以下に設置します(このディレクトリも設定可能です)。今回は、全ページで使われるレイアウトをlayout/default.html.erb として定義しています。
コントローラでどのレイアウトを使うかは、コントローラクラスに「layout 'default'」等と書くことで指定します。
コントローラ
最後に、アプリケーションの本体であるコントローラを見てみましょう。今回の単語帳アプリはとてもシンプルなので、コントローラは1つしか定義していません。
リスト2 コントローラの例(app.rb)
class Words < Ramaze::Controller
map '/'
engine :ERB
layout 'default'
def index
@words = Word.all
end
# (略)
end
コントローラクラスは、Ramaze::Controllerから継承させます。クラス名に決まりはありませんが、「 MainController」のようにControllerが付いた名前にするか、今回の「Words」のように操作する対象を複数形にした名前を付けることが多いようです。
Ramazeではコントローラクラスの最初にコントローラの設定を書きます。「 engine :ERB」「 layout 'default'」は前述の通り、ビューのための指示です。残りの「map '/'」は、このコントローラをどのようなURLに割り当てるかの指示です。今回は「'/'」に割り当てているので、「 http://localhost:7999/index」でindexメソッドが、「 http://localhost:7999/new」でnewメソッドが呼ばれます(indexメソッドはアクション名がない「http://localhost:7999/」というURLにアクセスされた場合にも実行されます) 。
indexメソッドは登録されている単語の一覧を表示します。といっても、コントローラではデータベースからデータを取ってくるだけで、あとの処理はview/index.html.erbで行っています。単語の一覧を作っている部分を見てみましょう。
リスト3 ビューの例(index.html.erb)
<ul>
<% @words.each do |word| %>
<li><%= a(word.name, :show, word.id) %></li>
<% end %>
</ul>
コントローラで用意した変数@wordsを使って、各単語の表示ページへのリンクを作成しています。aメソッドはRamazeのLinkヘルパーで用意されている、リンクタグを簡単に作成するためのメソッドです。「 ヘルパー」は、コントローラに便利な機能を追加するために用意されているRamazeの機構です。通常のヘルパーは「helper :cache」などのようにして読み込みますが、LinkヘルパーやRedirectヘルパーなどよく使われるヘルパーは読み込みなしで使えるようになっています。
単語のランダム表示
もう一つ、単語を一つランダムに表示するrandomメソッドの実装を見てみましょう。
リスト4 コントローラの例(app.rb)
def random
at = rand(Word.count)
@word = Word.first(:offset => at)
render_view :show
end
まず何番目の単語を表示するかを、Ruby組み込みのrandメソッドによってランダムに決めています。次に、表示する単語をデータベースから読み込みます。firstメソッドは、指定した条件を満たす最初のカラムを取得するDataMapperのメソッドです。
画面表示はshowメソッドと全く同じなので、view/random.html.erbは用意せず、render_viewメソッドでview/show.html.erbを表示させています。render_viewメソッドは前述のRedirectヘルパーの提供するメソッドです。
参考リンク
以上、駆け足ですがRamazeの機能と実践について解説してきました。より詳しい情報は以下のサイトを参考にしてください。
まとめ
4回に渡って、Rubyの新しいWebアプリケーションフレームワーク、SinatraとRamazeを紹介してきました。両者に共通するのは「シンプルさ」を追求する心です。コードがシンプルであれば、アプリケーションの全体を楽に把握することができます。アプリケーションの全てのコードが自分の思いのままになる楽しさをぜひ体験してみてください。
次回は、Railsのような高機能を指向したフレームワーク「Merb」が取り上げられる予定です。お楽しみに!