さて、今度はモデルを作ってみる。
% script/generate scaffold Post name:string title:string content:text
exists app/models/
exists app/controllers/
exists app/helpers/
create app/views/posts
exists app/views/layouts/
exists test/functional/
exists test/unit/
exists public/stylesheets/
create app/views/posts/index.html.erb
create app/views/posts/show.html.erb
create app/views/posts/new.html.erb
create app/views/posts/edit.html.erb
create app/views/layouts/posts.html.erb
create public/stylesheets/scaffold.css
create app/controllers/posts_controller.rb
create test/functional/posts_controller_test.rb
create app/helpers/posts_helper.rb
route map.resources :posts
dependency model
exists app/models/
exists test/unit/
exists test/fixtures/
create app/models/post.rb
create test/unit/post_test.rb
create test/fixtures/posts.yml
create db/migrate
create db/migrate/20090315021022_create_posts.rb
なんか大量に作成された。scaffold とは訳すと「足場」。
モデルの意味だろうか。今回はPostモデルを作成した。
これでPostを扱う一連のページが作成されたことになる。
モデルとは Java Bean のようなものだ。
まぁここら辺は他のMVCと変わらない。
今回のPostは name, title, context の3要素を持つ。
とりあえず、作られたファイルの簡単な説明が以下。
| post.rb | Postモデル。ActiveRecord::Base を継承するPostクラスを定義する。 |
| YYYYMMDDHHMMSS_create_posts.rb | CREATE TABLE文。ファイル名に日付が付いているのには意味がある |
| app/views/posts/XXX.erb | 各ERBファイル。これがViewとなる。 |
| app/views/layouts/posts.html.erb | 上で定義した各Viewの親となるView。ここに各Viewが埋め込まれる形になる |
| scaffold.css | その名の通り、スタイルシート |
| posts_controller.rb | メインとなる処理。ApplicationController を継承する PostsController クラスを定義する。 |
| posts_helper.rb | Postsのヘルパー。詳しくはまだ不明 |
| config/routes.rb | 前に説明したURLマッピング定義ファイル。ここに1文追加される |
| test/XXX | 各種テストケース |
さて、ここからRailsの本領発揮。
Railsはデータベース定義もコード同様に保守していく。
そしてテーブル定義の自動生成はもちろん、いつでも過去の状態に戻せる。
コードだけ過去の状態に戻しても、テーブル定義が新しいままで
プログラムが動かないなんて経験はよくあるだろう。
Railsではデータベースもコードの一部。
この考え自体は昔から僕が思ってたことだが、それをこうやって実践できるところがすごい。
% rake db:migrate (in /mnt/var/prog/rails/sample2) == CreatePosts: migrating ==================================================== -- create_table(:posts) -> 0.0038s == CreatePosts: migrated (0.0046s) ===========================================
これで、テーブルが作成された。

このように。
Railsのテーブルは必ずidカラムを持ち、これがPrimary Keyになる。
他に、schema_migrations というテーブルも作成される。
これでテーブル定義の履歴を管理する。
一通り準備は揃った。
トップページに、今作成したページへのリンクを張ってみよう。
/app/views/home/index.html.erb
<h1>Hello, Rails!</h1> <%= link_to "My Blog", posts_path %>
2行目の <%= ~ %> で囲まれた部分が、erbで埋め込んだRubyコード。
link_to というのが、リンク(Aタグ)を作るメソッドだろう。
第一引数が表示文字列、第二引数が遷移先。
ちなみにこの posts_path という変数、見たところどこでも定義されていない。
とりあえず、これが "/posts" に展開される。この謎はいずれ解明しよう。

これがpostsのindexページ。
少しViewファイルを見てみよう。
app/views/posts/index.html.erb
<h1>Listing posts</h1>
<table>
<tr>
<th>Name</th>
<th>Title</th>
<th>Content</th>
</tr>
<% for post in @posts %>
<tr>
<td><%=h post.name %></td>
<td><%=h post.title %></td>
<td><%=h post.content %></td>
<td><%= link_to 'Show', post %></td>
<td><%= link_to 'Edit', edit_post_path(post) %></td>
<td><%= link_to 'Destroy', post, :confirm => 'Are you sure?', :method => :delete %></td>
</tr>
<% end %>
</table>
<br />
<%= link_to 'New post', new_post_path %>
そんなに難しいことはやっていない。
@posts に、おそらくDBから取得したPost一覧が入るのだろう。
今はまだ何も投稿していないので、for ~ end の部分はスルーされる。
この中身は後で見ていくことにする。
最後に link_to。
ここの new_post_path が、"posts/new" に展開される。
まだこの部分が謎だが、何らかのルールに従ってるはずなので
いずれそのルールを解明しよう。
先にViewを見てしまったが、Controller の方も見ておこう。
app/controllers/posts_controller.rb
def index
@posts = Post.find(:all)
respond_to do |format|
format.html # index.html.erb
format.xml { render :xml => @posts }
end
end
予想した通り、@posts にはPost一覧を取得していた。
@ で始まる変数は、Javaでいうところのフィールド。インスタンス変数である。
あとは画面表示だけ。xmlでも表示できるらしいが、その部分はまた後にしよう。