Rails 2.0のscaffoldを使ってみた
Ruby on Rails 2.0になって何が変わったのか俯瞰してみるには、とりあえずscaffoldを作ってコードを見てみるのがよかろう、と思ったので作ってみた。
ありがちで恐縮だが、Personモデルのscaffoldを作る。要素は名前(name)と年齢(age)の二つだけ。シンプル。
まず、アプリケーションの初期化を行う。DBはお手軽に扱いたいのでsqlite3を使うことにした。これだとconfig/database.ymlの編集も不要なので楽。
$ rails trial -d sqlite3 (略) $ cd trial
で、Rails 1.2であれば、まずはmigrationファイルを作ってDBにmigrateし、その後でおもむろにscaffold生成を行うところである。しかし、Rails 2.0ではここでいきなりscaffoldの生成を始める。
$ ruby script/generate scaffold person name:string age:integer exists app/models/ exists app/controllers/ exists app/helpers/ create app/views/people exists app/views/layouts/ exists test/functional/ exists test/unit/ create app/views/people/index.html.erb create app/views/people/show.html.erb create app/views/people/new.html.erb create app/views/people/edit.html.erb create app/views/layouts/people.html.erb create public/stylesheets/scaffold.css dependency model exists app/models/ exists test/unit/ exists test/fixtures/ create app/models/person.rb create test/unit/person_test.rb create test/fixtures/people.yml create db/migrate create db/migrate/001_create_people.rb create app/controllers/people_controller.rb create test/functional/people_controller_test.rb create app/helpers/people_helper.rb route map.resources :people $
出力を見ると、migrationファイルが一緒に生成されているのがわかる。Rails 2.0ではこいつもscaffoldジェネレータが面倒を見ることになったのだ。ついでに、テンプレートファイルの名称がXXX.rhtmlからXXX.html.erbに変更されているのも見てとれる。
そして、オプションとして与えているname:stringとage:integerに注目。従来はscaffoldジェネレータが勝手にDBのスキーマ情報を参照して表示・編集するフィールドを定めていたが、今回はスキーマを作る前にジェネレータを使うので、それができない。従って、modelのどのフィールドを対象とするのか、プログラマが明示的に指定する必要がある。これを指定しないと、何も表示せず何も編集できない退屈なscaffoldが作られてしまう。また、migrationファイルもこのパラメータに従って作られている。
class CreatePeople < ActiveRecord::Migration def self.up create_table :people do |t| t.string :name t.integer :age t.timestamps end end def self.down drop_table :people end end
migrationファイルも新スタイルであるが、まぁどう書けばよいかは見た目から察することができると思う。見てのとおり実に単純な設定なので、NOT NULL制約やらサイズ制限やらを足したい場合は手を加えるべし。今回はこのまま使うことにする。
そして、migrate。
$ rake db:migrate (in /home/idesaku/temp/trial) == 1 CreatePeople: migrating ================================================== -- create_table(:people) -> 0.0372s == 1 CreatePeople: migrated (0.0441s) ========================================= $
ちなみに、従来通り先にmodelとmigrationファイルの生成を行ってからscaffoldを作ろうとすると、「すでに同名のmigrationファイルがある」といったエラーが出てscaffoldの生成処理が停止する。--forceオプションを加えても上書きしない(されても困るが)。この場合、--no-migrationオプションを加えて実行すること。
あとはこれまでと変わらない。
実際にページを表示したときにレコード数ゼロだと寂しいので、適当に足しておこうか。本当はmigrationファイルにレコード追加処理も書いておくべきなのだろうが、面倒なので今回はscript/consoleを使ってちゃっちゃと突っ込んでしまう。
$ ruby script/console Loading development environment (Rails 2.0.1) >> 10.times do ?> Person.create(:name => "Miku Hatsune", :age => 16) >> end => 10 >> quit $
そして、サーバ起動。
$ ruby script/server
で、ブラウザでhttp://localhost:3000/peopleにアクセス。
でてきた。どうでもいいがみっくみくである。
ところでpaginationが標準から外れてプラグイン化したわけだが、Rails 1.2のscaffoldではpaginationを利用していたはずだ。Rails 2.0ではどうしているのであろう?と思い調べてみたのだが・・・単にpaginationを使わないようになっていた。
New personもちゃんと表示される。
generate時にname:stringやらを渡したが、あれをやっておかないと、ここが空っぽになる。
ちなみに、http://localhost:3000/people.xmlにアクセスすると・・・。
一覧表示していた内容がXML形式で送られてくる。REST対応の一環である。
このへん、コントローラではこんな書き方をしている。
# GET /people # GET /people.xml def index @people = Person.find(:all) respond_to do |format| format.html # index.html.erb format.xml { render :xml => @people } end end
Rails 1.2のそれにXMLのレスポンスを追加してあるのだが、これがRails 2.0のスタイルってわけである。Rails 2.0はRESTfulなのだ。
とりあえずここまで。
Rails 1.2の頃と比べて手順とお作法にいくらかの違いがあるものの、使い勝手はおおむね変わらない。むしろ、modelがscaffoldジェネレータの管理下に入ったのは、手順が一本化されてすっきりとして良い感じだ。ただ、Rails 1.2向けに作られた既存の入門書通りに操作してもいろいろトラブるわけで、Rails入門者は涙目かもしれんな。まぁそういう人々はしばらくは1.2使っていればいいか。