読者です 読者をやめる 読者になる 読者になる

ミームの死骸を待ちながら

We are built as gene machines and cultured as meme machines, but we have the power to turn against our creators. We, alone on earth, can rebel against the tyranny of the selfish replicators. - Richard Dawkins "Selfish Gene"

We are built as gene machines and cultured as meme machines, but we have the power to turn against our creators.
We, alone on earth, can rebel against the tyranny of the selfish replicators.
- Richard Dawkins "Selfish Gene"

Rails初心者はどうやって他人のRailsコードを読めばいいか

ちょこちょこ更新記事 Rails


先日のエントリ などなかったかのように別の話題です。
(どうやらRails 1.1の知識で書いてしまったらしく、浦島太郎状態。最新版の読み方にちまちま変更していく)
Railsは過保護なのでたくさんの決まりがあり、ユーザーはその決まりに則ってアプリを作る。CoC (Convention over Configuration) というやつ。決まりを覚えてしまえばラクチンなのだが、まだいまいち覚え切れていない時に「完成品」を見せられると混乱する。
つまり、他人が書いたコードを見ても、どこまで自動生成され、どこからその人が書いたコードなのか区別が付きにくいのです。
そこで、自分で入門するのではなく他人の書いたコードを読む必要が出たRails初心者のために最低限必要な知識をまとめた。というか、まぁ、バイトで社員さんの書いたRailsコードを読むところから始めているので、復習がてら、八割がた自分のためです。言葉の使い方とか所々間違ってる可能性が高いので、あまり鵜呑みにしないように。


まず見るべきは、app/フォルダ下。ここにはMVCのキモであるModel, View, Controllerの三つが入っている。MVCとは、Webアプリケーションを、データ(データベース周り: Model), 表示(HTMLとか: View)、CGI処理 (Rubyスクリプトとして、どのデータをいつ取り出してどこに表示させるか…という部分を指定している: Controller)の三つに分けて考える方法。

以下では、「先輩の書いたコードを必死こいて読んでいる」という設定で話を進める。


app/models


この下に入っているhogehoge.rbファイルは全てモデルをジェネレートした時に自動生成されたもの。具体的に言えば、

> ruby script/generate model Hello

とすると、以下のファイルが生成される(重要なもののみ)。

  • app/models/hello.rb
  • db/migrate/001_create_hellos.rb

modelsフォルダ下にある一つめのhello.rbは、Helloモデルがクラスとして実装され、AcriveRecodeクラスを自動的に継承されたもの。コードで言うと

class Hello < ActiveRecord::Base
end

という2行(プラス、コメント)。これ以外のコードが入ってたら先輩が追加したもの。これしか書かれてなければ、モデル作ったままいじっていないことになる。
ただ普通は複数のモデル (テーブル) 間の関連を記述しているので、belongs_toとかhas_manyとか書かれているはず。これに従ってUML図とか書いてみれば、全体のデータがどう管理されているかがわかる。ここ重要。

次に、001_create_hellos.rb。これはマイグレーション定義ファイルと言って、データベースのカラムをいじりたい時はこのファイルを変更して

> ruby script/generate migration HogeHoge

とかやる...んだっけ。001の数字はデータベースを書き換える事に上がっていって、「しまった間違えた!」という場合は過去の任意のバージョンに戻すことができる。
(追記)Rails2.0以降では、通し番号の代わりに「YYYYMMDDHHMMSS」形式でタイムスタンプが押されるようになった。200806071133705_create_hellos.rbてなかんじ。これで多人数開発時のバージョンのバッティングがなくなった。

app/controllers


コントローラは、一般的なCGIで言うディレクトリに相当。このディレクトリに、各CGI (アクション) がまとめられている*1
とりあえずapp/controllers下のファイルを見てみる。ここには

  • application.rb
  • hello_controller.rb

などがある。application.rbはRailsプロジェクトを作ったとき自動的に作られるコントローラ。それ以外のhello_controller.rbなどは、またしても

> ruby script/generate controller Hello

と、ジェネレータを使って生成されたもの。このコマンドを実行するといろいろ出来るんだけど、重要なのは

  • app/controllers/hello_controller.rb
  • app/views/hello*2

の二つ。とりあえず今注目しているhello_controllers_rbの中身を見てみる。初期状態では

class HelloController < ApplicationController
end

となっているはず。ここに何も書かないと、同名のViewに処理が渡されて(?)指定のファイルを表示させてくれるんだけど、普通はいろいろ処理が書いているはず。こんなかんじに↓

class HelloController < ApplicationController
    def index
        xxxxxx
    end

    def show
        xxxxxx
    end

    def new
        xxxxxx
    end

    def edit
        xxxxxx
    end
end

ずらずらとメソッドが定義されている。この各メソッドが、CGIアクションに相当する。すなわちブラウザで見るとき、www.example.com/hello/indexと入力すると、hello_controller.rbiのindexメソッドが実行される*3


app/views

さてcontrollerのメソッド実行結果は、同名のView*4に渡されて何らかの表示処理をなされるのが普通。そこで先輩の書いていたcontrollerのメソッドから一つ選んで、対応するViewを見てみるとする。

# まずcontrollers中
class HelloController < ApplicationController
    def index
       @message = "Hello, Rails!" 
    end
.
.
.

という処理を追うことにする。www.example.com/hello/indexにアクセスすると@messageというインスタンス変数*5に文字列"Hello, Rails!"が代入される。この処理が終わると、同じ"index"という名のViewファイル、app/views/hello/index.rhtml*6を評価する。

#これはviews内のindex.rhtml
<%= @message %>

こうなってる。indexメソッドで評価された@messageの値がそのまま渡っているので、ページにHello, Rails!と表示されるはず。Viewにも一応Rubyスクリプトを埋め込めるのだが、こちらは最小限にしてCGI処理はControllerのほうにまとめた方がいい、とか聞いた気がする。
ちなみに、上のように<% と %>で囲まれた中身はRubyコードと見なされ、動的に実行される。<%=とか<%-とか<%#とか色々種類あるのでマニュアル参照(逃げた)。


実際に社員さんのコードを読んで

コントローラのメソッド内でrespond_toという機能が多用されていた。これはどうやらRails 1.2から本格的に実装された機能であり、AcrionPackの最大のDRYになりうる、と参考文献に書かれていた。できる。ここは要勉強だな。
(20080607追記)respond_toを簡単に言えば、その名のとおり、渡されるファイルの形式によって(respond to file type)挙動を変えてくれるメソッド。どうやらコントローラを作成したらデフォルトで追加されているらしい。またひとつ覚えることが増えた。
くまくまーの中の人の記事が分かりやすい。->500 Internal Server Error

参考文献

Ruby on Rails入門―優しいRailsの育て方

Ruby on Rails入門―優しいRailsの育て方

2006年に買ったんだけど、

Railsアプリ -> Rubyで文字列処理など雑用 -> Java -> オブジェクト指向 -> Rails

という(ちょっと妙な)流れで一週してきてから読み直すと、さらに深く理解できる。いい本だ。

理解はいいけど、手を動かせというアレですね。はい。すんません。

*1:実際はディレクトリ構造なんてなくて、処理はdispatcherとやらが制御しているらしいが細かいことは置いておこう

*2:こいつはディレクトリ

*3:注: publicなメソッドのみ、アクションとして実行されうる

*4:さっきscript/generateしたとき同時に作られた!

*5:@が着いた変数はインスタンス変数で、RailsではController -> Viewへと値を持って行くことができる

*6:rhtmlは普通のHTMLに埋め込みRuby処理能力を持たせた形式