Railsの全体像を知ろう:Ruby on Rails3で学ぶWeb開発のキホン(2)(2/2 ページ)
Railsは、機能ごとに異なるコンポーネントで構成されています。Railsの全体像を見渡すために、今回はこのコンポーネントの種類や機能を紹介します。
ActiveSupportを使いこなそう
Railsを構成する部品の中で、もっとも汎用的なライブラリがActiveSupportです。ActiveSupportは、いわば「素のRubyにちょっとした便利な機能を付け加える」役目を果たしています。Webアプリケーションやデータベースといった個別の課題とは直接関係しない、Rubyそのものを強化するような汎用的なライブラリなので、Railsを使って開発するときだけでなく、幅広くRubyを使った開発で便利に活用できるでしょう。
素のRubyとの区別
Railsで開発しているとき、ある機能がRubyにもともとあるのか、ActiveSupportによって追加されたのかを判断できることは重要です。これには主に2つの理由があります。
1つめは、その機能についてどのドキュメントを読めばいいかが違ってくるからです。一生懸命Rubyのマニュアルを探したのに見つからなかった、というようなことがあっては時間の無駄です。2つめの理由は、Rubyの機能だと思い込んでいると、Railsでない環境や、irbで直接コードを実行するときなどに、思いがけずメソッドがないというエラーになって混乱する危険があります。この他、ActiveSupportの機能をRubyの動作だと思い込むというのは典型的な初心者の姿でもあるため、両者を区別できないまま使っていると、恥ずかしい思いをするかもしれません。これらの理由から、代表的なActiveSupportのメソッドについてはRubyとは区別して頭に入れておくことをお勧めします。
よく知られたActiveSupportの機能
ActiveSupportは、非常に幅広い機能を提供しています。よく知られている機能としては、Object、String、Array、Hash、DateといったRubyの基本的なクラスに便利なメソッドを追加しています。ここでは代表的なものを順に紹介していきます。
empty?と似た「blank?」
もっとも使う頻度の多いメソッドの1つが、すべてのオブジェクトで利用できるblank?インスタンスメソッドです。文字列や配列には、空であるかどうかを調べるためのempty?メソッドがありますが、これは、対象のオブジェクトにempty?メソッドがないと呼べないため、対象がnilである可能性がある場合は次のようなコードを書く必要がありました。
if !array || array.empty? # 配列がnilか、要素がないとき特有の処理 end
このように毎回、対象となるオブジェクトがnilかどうかをチェックするのは面倒ですし、うっかりチェックし忘れて例外が出てしまう事故も起こりがちです。 blank?は、このような場合に便利に使えます。ActiveSupportのロードされた環境では、上記のコードはblank?を使って次のように書くことができます。
if array.blank? # 配列がnilか、要素がないとき特有の処理 end
とてもすっきり書けますね。
対象が文字列の場合は、blank?は単に「nilであっても大丈夫」という以上の仕事をします。具体的には、空白文字(半角スペース、タブ、改行など)のみの文字列では、blank?がtrueとなります。この場合、empty?とは結果が違うので注意が必要です。
" ".empty? => false " ".blank? => true
Rails内部では、このblank?の動作がさまざまなところで利用されます。例えば、モデルの属性値の検証で、validates_presence_of(属性値が存在しないと検証エラーとする)という機能がありますが、これにもblank?が使われるため、半角スペースのみの値も検証エラーになるといった動作になります。
余談ですが、筆者の経験では、blnak?はあまりにも基本的かつ便利なため、Railsの初心者はこれをRubyの機能だと信じていたり、ところかまわず乱用する傾向があります。確かにblank?はempty?に比べて例外が起こりづらく、その意味で「安全なempty?」であるかのように思えるかもしれません。しかし、empty?を使うべきところでblank?を使うのは必ずしも適切とはいえません。具体的には、「対象がempty?メソッドを持っていることが明らかで(nilでないことが明らかで)、単純にそれが空であるかどうかを確認したい」場合は、empty?が適切です。このようなところに blank?を書くと、ソースコードを読む人は、書き手の意図を誤解する可能性があります。blank?は、対象がnilなどempty?メソッドのないオブジェクトであるかもしれない場合や、半角スペースなどを考慮した判定を行いたい場合に使うと覚えておきましょう。
クラス名やテーブル名などの変換やクラスの取得
Railsのプログラミングでは、クラス名、テーブル名、カラム名、属性といった名前を扱いたい場面がよくあります。Rubyではメタプログラミングといって、プログラム自体をプログラムによって動的に作ることが多いので、これらの名前を自在に扱ったり、名前から簡単に対応するクラスオブジェクトを取得できることは重要です。ActiveSupportは、これらを簡単にするためのいろいろなメソッドを追加しています。
まず、Stringのpluralizeとsingularizeがあります。それぞれ、英語の名詞を表す文字列を複数形にしたり、単数形にしたりするメソッドです。Railsでは、テーブル名を複数形で命名するのが標準なので、例えばテーブル名を類推したり、逆に対応する単数形の名前を得たりするのに便利に使えます。
"card".pluralize => "cards" "cards".singularize => "card"
また、ActiveRecord::Baseといったクラス名の表記と、active_record/baseといった、いわばファイルのような表記の間での変換機能もあります。前者から後者にするにはunderscore、逆はcamelizeを使います。
"ActiveRecord::Base".undersocre => "active_record/base" "active_record/base".camelize => "ActiveRecord::Base"
また、このようにして得たクラス名の文字列からクラスオブジェクトを得るための簡単なメソッドも用意されています。次のように、constantizeによって得ることができます。
"ActiveRecord::Base".constantize => ActiveRecord::Base
Timeクラス、Dateクラスへの拡張
日付を表すTimeクラスやDateクラスにもさまざまな拡張がされています。数が多いので、すべてを紹介することはできませんが、例えばTimeクラスには、月の日数を返すdays_in_monthメソッドが追加されています。
Time.days_in_month(2, 2000) => 29 Time.days_in_month(2, 2011) => 28
この他にも、例えば、あるTime/Dateオブジェクトから「その日の最後の時刻」「その月の最後の時刻/日付」を得るメソッドが提供されています。
Date.today.end_of_day Time.now.end_of_day Date.today.end_of_month Time.now.end_of_month
また、ここでは詳しくは触れませんが、タイムゾーンを扱うためのメソッドも追加されています。
to_json
Railsアプリケーションを開発する上でお世話になることの多いメソッドの1つに、to_jsonがあります。配列やハッシュ、モデルオブジェクト(ActiveRecordオブジェクト)などを自動的にJSON文字列に変えてくれる便利なメソッドです。よくある使い方としては、ブラウザ側のユーザーインターフェイスをJavaScriptで実現し、サーバ側はただデータを提供するだけの場合、サーバ側ではこのto_jsonを使ってデータをJSON表現にしてレスポンスとして返します。
['a', 'b', 'c'].to_json => [\"a\", \"b\", \"c\"] {:name => 'Tama', :type => 'Cat'}.to_json => {\"name\":\"Tama\",\"type\":\"Cat\"}
モデルクラスなどでは、to_jsonの返す内容をカスタマイズすることも可能です。例えば、すべての属性の内容を返すのではなく、必要最低限の内容だけを返すようにするといったカスタマイズを行うことがあります。
数値への拡張
数値にも拡張が加えられています。例えば、ある数で割り切れるかをmultiple_of?で調べることができます。
121.multiple_of?(11) => true 122.multiple_of?(11) => false
この他、奇数/偶数を調べるodd?/even?などが追加されています。
ActiveSupportの全体像
最後に、ActiveSupportの提供する機能の全体像は次のようになります。
- コアクラスの拡張
- Array、BigDecimal、Class、Date、DateTime、File、Float、Hash、Integer、Kernel、Module、Numeric、Object、Process、Range、String、Time、他
- 汎用機能
- コールバック
- キャッシュ
- ライブラリの自動ロード
- 名詞の活用
- JSON
- ロケール
- 順序付きハッシュ(ActiveSupport::OrderedHash)
- 文字列とシンボルをキーとして同一視するハッシュ(ActiveSupport::HashWithIndifferentAccess)
- 引数に利用するオプション関係のユーティリティ
- タイムゾーンのサポート etc
- 設定値
- Unicode、タイムゾーンに関する設定値
なお、本記事では詳しく取り上げなかったコアクラスの拡張の中にも、比較的利用局面が多いものや有名なものが少なくありません。主なものを以下の表でご紹介します。興味を持たれた方はAPIリファレンスを参照してください(例えばArrayへの拡張は、Arrayの項で見ることができます)
クラス名 | 利用局面の多い拡張(まだ取り上げていないもの) |
---|---|
Array | extract_options! |
Class | cattr_accessor/cattr_reader/cattr_writer |
Module | alias_method_chain/delegate/mattr_accessor |
Date/Time/DateTime | months_ago/next_month/since/to_formatted_s/to_date/to_time/to_datetime |
Hash | reverse_merge/slice/except/stringfy_keys/symbolize_keys |
Numeric | ago/bytes/days/hours/minutes/seconds/since/weeks |
Integer | years/months |
Object | present?/reload!/returning/try/with_options |
String | demodulize/encode_json/html_safe/humanize/truncate |
今回のまとめ
本記事では、前回に続いてRailsの全体像を知るために、フレームワークを構成する部品について概観しました。また、その中でも基本的・汎用的な位置づけであるActiveSupportについて、よく使われる機能をピックアップして詳しく解説しました。Railsという環境の上で開発することで、いろいろなことが便利に行えるということを感じていただけたのではないでしょうか。
次回からは、いよいよRailsの詳しい内容を見ていくことになります。まずは、モデル層のActiveRecordについて解説していきます。
Copyright © ITmedia, Inc. All Rights Reserved.