Initializerとは?

File.dirname(filename)はfilenameの一番後ろのスラッシュより前の文字列を返す。もしスラッシュがなければカレントディレクトリ(つまり".")を返します。
__FILE__はRubyの組み込み変数で現在のソースファイル名です。似たようなので$0というのもありますがこちらは実行中のスクリプトファイルを表します。Rubyではよく出てくるので違いをしっかり覚えておきましょう。
定数RAILS_ENVが定義されていなければ定義する。環境変数RAILS_ENVがセットされていればそれを用い、それがなければdevelopmentをセットする。
Object#dupを使って複製しているのがちょっとよく分からない。複製していないとRails起動中にENV['RAILS_ENV']が代えられてしまった場合、内部動作に整合性が保てなくなってしまうからだろうか。なかなかどういうときにdupすればよいかというのは難しそうだ。というよりうっかり書き忘れてしまいそうだ。
ここでInitializerにせずselfにしたのはひょっとするとクラス名を変更したい、あるいはaliasしたいといった場合があるからである。クラス定義文の中ではなるべくクラス名は書かずにselfとしておいた方が継承したときなどにいろいろ厄介ごとがなくて済む。
個人的にはどこで定義されているのか混乱してしまうのでクラスメソッドのレシーバ省略はあまりしたくないのですが、省略する方が一般的なのでしょうか?やっぱり派閥に分かれているのかも。まぁできるだけ省略したくないと思うのはそれだけ使い込んでないということなんだろうと思う。今回すぐにクラスメソッドの省略が見抜けなかったのも経験不足ゆえだろう。
次の行はInitializerの任意のインスタンスメソッドをObject#sendを使って実行させている。デフォルトではprocessメソッドが実行されるらしい。
確か1.8以降だとObject#__send__を使わないと警告が出るんだったような気がする。ここらあたりはどうやって回避しているのだろうか。もしかすると再定義されたメソッドなのかもしれない。自分で探してみた感じどうもそれっぽいのが分からないのですがどうなんでしょうか?
ここで先にConfigurationクラスを呼んだ方が理解しやすいので一旦Configurationクラスの基本的なところを押さえておく。
アクセサにズラーと初期値を代入している。初期値は"default_" + アクセサ名のメソッドで定義してある。
カッコが省略されているのでわかりづらいがそれ以前にroot_pathやenvironmentといったローカル変数が定義されていないのでこれはメソッドだ。ということで探してみると案の定あった。
書き方からしてDir.glob()のaliasのようだなと思って探してみたらRuby標準で定義されてた。ActiveSupport拡張だと思ってた。今まで知らずに全部Dir.globとか書いてたよ…。ワンライナーとか全部Dir[]に変更だな。
というより考えてみたら当たり前なのだけど、クラスメソッドに[](args)といったメソッドを定義すれば組み込みメソッドみたいに使えるのね。最初はDirといった定数にハッシュを入れておいてそれにアクセスだとか、Kernel#Dir(array)といったメソッドを定義しておいてそれのカッコの省略なんじゃないかと疑った。
File.expand_pathは相対パスの文字列を絶対パスへ展開する。その際、第2引数を基準にする。第2引数が無ければカレントディレクトリとみなす。~の展開もしてくれるらしい。
つまり、Railsライブラリの置いてあるディレクトリのbuiltin/controllers/にコントローラを置くことも出来る。
コンストラクタの最後では、フレームワークそれぞれのアクセサメソッドにOrderedOptionsクラスのインスタンスを渡している。
"config/database.yml"からYAMLファイルを読んできてRubyのデータ構造へ戻す。興味深いのはあいだにERBを挟むことでYAMLファイル内でRubyコードを入れることが出来るようにしている点である。
OrderedHashクラスはArrayを継承している。名前どおり順番を保持したHashを実装している。実装は特に難がなさそうなので飛ばす。順序つき配列を使いたいケースは結構あるので一応こんなのがあったと頭にとめておくと参考に出来る。
ここで注意することは、OrderedOptionsがキーとして文字列を取るのに対し、OrderedHashはキーとしてシンボルをとる。ActiveSupportをまだrequireしていないのでシンボル・文字列間の自動変換はやってくれない。
メソッド名が分かりやすいので何の処理を行なっているかが読んだだけで大体は分かる。分かりにくいところ・気になるところだけ以下補足。
どうもRubyの1.8.2と1.8.4以降ではRailsは動作して、1.8.3は動かないらしい。どうしてかよく分からない。安定版と開発版が交互だったのだろうか。でもここ最近は1.9.1が開発版だし、1.8.3がそんな前とも思えない。
silence_warningsというメソッドが定義されている。名前だけでも十分機能を想像できるが一応読んでおく。
多重代入を用いて$VERBOSEを一旦old_verboseに非難しておいて$VERBOSEにnilを代入する。今まであまり多重代入は使ってこなかったけど、こういうケースだと意味も明確になるので良さそうな気がする。
このメソッドの難点は警告が使っている間全く表示されないことだろう。Rubyのバージョンが変わって警告が出るようになっても気づかない恐れもある。警告は煩わしいが、出すには出すなりの理由があると思う。
例えば、先ほども出てきたObject#sendは使うと警告が出る。何故かといえば、sendはよくありそうなメソッド名だからだ。だからObject#__send__を推奨するようにメッセージが出てくる。うっかりユーザがsendメソッドを追加してしまったらどこかでハマりになる恐れがあるような気もする。
Array#- は集合の差を返すメソッドである。2行前でconstをself.class.constantsとしたあとに、"config/environment.rb"を読み込んでいることから、"config/environment.rb"はInitializer::定数名を定義することを期待されているようだ。変更されたものだけ定数をセットする。こんな回りくどいやり方をしているのは定数に再代入しようとしたら例外が起こるからだろう。
RAILS_DEFAULT_LOGGERが定義されていたら、何もせずに抜けるようだ。つまり独自のloggerを使いたければコンストラクタでRAILS_DEFAULT_LOGGERを定義しておけば良いようです。でも、その処理はどこに書けば良いのだろう・・・。
これによりブラウザをリロードするだけでコードの変更を反映できるという開発の快適性を実現している。
このファイルをのぞいてみると、NilClassを拡張している。コメントを読むと、どうやらnilに伴うエラーの際にデバッグしやすくするための拡張のようだ。
まず、あるクラスからObjectクラスに定義されているパブリックインスタンスメソッドの配列の差集合を取ることで独自に定義されているメソッド名を割り出している。
その後、メソッド名をキー、クラス名を値としたハッシュとしてキャッシュしておくことでメソッドを呼び出そうとしたがnilクラスのためメソッドが定義されてないと例外を発生させる以上のことをすることが出来る。
method_missingでraise_nil_warning_forを呼び出すことでユーザがどのクラスを使おうとしていたのかということまで教えてくれる。
ActiveRecord::BaseとArrayに対してこの機能を有効にしているのだけど、これが拡張できるとうれしいケースが他にもあるかもしれない。(ちょっと今は思いつかないけど)
Object#__send__を利用してそれぞれのアクセサにアクセスする。それぞれのアクセサの値には前に見たようにOrderedOptionsクラスのインスタンスがセットされているので、eachを使うことが出来る。
と受けることでブロックはProcオブジェクトへ変換される。(yieldで受けた場合は変換されない。そのためyieldを使う方が若干速いという説がある)
ブロックは単なるProcオブジェクトになったのでインスタンス変数に代入できる。その結果、変数名.callするだけでコールバックすることが可能。(コールバックの意味合いがちょっと違うような気もする。)
これでとりあえずinitializer.rbはこれで終了。色々なテクニックが駆使されていてかなり面白かった。さすがにこれだけの量の文章を書くのは大変だったけど。
次はどこを読むかまだ決めていない。何かリクエストかお勧めがあればコメント・TBで教えてくださいな。
I sort my thought... - クリスマスパーティーのプレゼント交換プログラムのテストを書く
I sort my thought... - 文字列をマルチバイト文字を意識せずに扱えるようなラッパークラス
アメブロ、クチコミ促進サービス「AmebaPR」を活用した広告商品を講談社と共同開発:ニュース - CNET Japan
ぴょぴょぴょ? - Linuxとかプログラミングの覚え書き - - Changelogのための英文テンプレート集

[ 206] Rails::Initializerを読む。 - I sort my thought...
[引用サイト]  http://d.hatena.ne.jp/walf443/20060707/rails_initializer



お気に入り



  • track feed
    • seo