3rdRailによるRailsプログラミング入門

第2回 ActiveRecordが提供するModel機能を理解しよう

富田 陽介
Banana Systems株式会社

2009/4/24

Railsアプリケーション開発を支援する統合開発環境「3rdRail」を使って、開発、デバッグ、プロファイリングの手法をマスターしよう(編集部)

 第1回では、「初めてのRailsアプリケーション開発」と題して、Railsが提供するscaffoldという支援機能を使用してシンプルなWebアプリケーションの開発の流れを紹介しました。

 これから3回連続で、「つぶやき」アプリケーションを拡張/機能追加しながら、ModelクラスとControllerクラスの開発ステップを見ていきます。第1回で紹介しきれなかった3rdRailのIDEとしての機能を取り上げながら、より実践的なWebアプリケーションの開発手順に触れてみましょう。

 今回は、ActiveRecordが提供するModel機能(ファインダ、バリデーション、アソシエーション、マイグレーション)について紹介します。

関連記事:
リンク 生産性を向上させるRuby向け統合開発環境カタログ
http://www.atmarkit.co.jp/fcoding/articles/rubyide/rubyidea.html
リンク @IT Coding Edge Ruby/Rails関連記事インデックス
http://www.atmarkit.co.jp/fcoding/index/ruby.html

ActiveRecordが提供するModel機能

 第1回では、3rdRailのリソースの新規作成機能を使用して作成したHitokotoモデルが、ActiveRecord::Baseクラスを継承して作成されていることを紹介しました。また、ActiveRecord::Baseで定義済みのfindメソッドを使用すると、SQLを意識せずにデータベースに保存されているレコードへアクセスできることも確認しました。

 ActiveRecordが提供するModelの機能はこれだけではありません。今回は、以下の機能について、実際に動作を見ながら確認していきましょう。

ファインダ
検索条件を指定し、DBから条件に合致したレコード群を取得します
バリデーション
Modelクラスインスタンスの各属性が保持すべき条件(データの存在有無や文字列長、フォーマットなど)を指定し、この条件への適合状態を検証します
アソシエーション
異なるModelクラスの間にある関連を定義します
マイグレーション
Model定義の追加/更新に合わせてDBスキーマを更新します

 ファインダ機能を試してみるために、サンプルデータをいくつか登録しておきましょう。[Railsエクスプローラー]の[コントローラー]−[Hitokotos]−[アクション]ツリーを展開してください。ここでindexを右クリックして、[実行]−[サーバーで実行]を選ぶと、3rdRailウィンドウ内のブラウザでアプリケーションへアクセスできます。

 ここでは、以下のとおりのサンプルデータを登録したとして話を進めます。

サンプルデータ
id|hitokoto|created_at|updated_at
1|Apple|2009-03-31 00:00:00|2009-03-31 00:00:00
2|Orange|2009-03-31 01:00:00|2009-03-31 01:00:00
3|Banana|2009-03-31 02:00:00|2009-03-31 02:00:00
4|牛乳|2009-03-31 03:00:00|2009-03-31 03:00:00
5|からあげ|2009-03-31 04:00:00|2009-03-31 04:00:00
6|Banana|2009-03-31 05:00:00|2009-03-31 05:00:00

Hitokotoのindex表示(画像をクリックすると拡大します)
Hitokotoのindex表示

 サンプルデータが登録できたら、アプリケーションサーバは停止しておきましょう。ウィンドウ下部の[サーバー]タブから、始動済みになっているサーバを右クリックして[停止]を選択すれば、アプリケーションサーバを停止できます。

ファインダの動作確認

 それでは、ActiveRecordにより定義されているファインダの機能を使用し、データベースから先ほど登録したサンプルデータを取り出してみましょう。

 動作確認には、3rdRailのRailsコンソール機能を使用します。3rdRailのメニューから、[ウィンドウ]−[Railsコンソール]−[最後または新規のコンソール表示]の順にクリックすれば、ウィンドウ下部の[コンソール]タブにRailsコンソールが表示されます。

Railsコンソール(画像をクリックすると拡大します)
Railsコンソール

 このコンソールでは、Railsアプリケーション上で対話的にコードを実行することが可能です。以下のメソッドをコンソールに入力し、データベースからid=1のHitokotoレコードを取得してみましょう。

>> h = Hitokoto.find(1)
=> #<Hitokoto id: 1, hitokoto: "Apple", created_at: "2009-03-31 00:00:00", updated_at: "2009-03-31 00:00:00">

 このようにid=1のレコードが正しく取得できたでしょうか。ここで実行したメソッド「ActiveRecord::Base#find(Fixnum)」では、引数として渡された数値をidに持つレコードをデータベースから取得します。このメソッドを実行すると、実際には以下のようなSQLが実行されます。

SELECT * FROM "hitokotos" WHERE ("hitokotos"."id" = 1)

 ActiveRecord::Baseを継承したクラスのインスタンスでは、対応するテーブルのカラムに対応したアクセサが自動的に定義されます。次のようにすれば、レコード中の値に簡単にアクセスできます。

>> h.hitokoto
=> "Apple"
>> h.created_at
=> Tue, 31 Mar 2009 00:00:00 UTC +00:00

 ほかのファインダも試してみましょう。以下のメソッドでは、Hitokotoクラスのすべてのレコードを配列で取得します。

>> hs = Hitokoto.find(:all)
=> [#<Hitokoto id: 1, hitokoto: "Apple", created_at: "2009-03-31 00:00:00", updated_at: "2009-03-31 00:00:00">, #<Hitokoto id: 2, hitokoto: "Orange", created_at: "2009-03-31 01:00:00", updated_at: "2009-03-31 01:00:00">, #<Hitokoto id: 3, hitokoto: "Banana", created_at: "2009-03-31 02:00:00", updated_at: "2009-03-31 02:00:00">, #<Hitokoto id: 4, hitokoto: "牛乳", created_at: "2009-03-31 03:00:00", updated_at: "2009-03-31 03:00:00">, #<Hitokoto id: 5, hitokoto: "からあげ", created_at: "2009-03-31 04:00:00", updated_at: "2009-03-31 04:00:00">, #<Hitokoto id: 6, hitokoto: "Banana", created_at: "2009-03-31 05:00:00", updated_at: "2009-03-31 05:00:00">]

 上記で実行したActiveRecord::Base#find(:all)は、その引数に、シンボル:allが渡されていることから推測できるように、データベースから該当のレコードをすべて取得します。

 さらに、検索条件を追加したファインダも試してみましょう。以下のメソッドでは、idカラムではなく、hitokotoカラムへの検索条件を指定して検索を行います。

>> Hitokoto.find_by_hitokoto("Orange")
=> #<Hitokoto id: 2, hitokoto: "Orange", created_at: "2009-03-31 01:00:00", updated_at: "2009-03-31 01:00:00">

 ここで「おやっ」と思われた方もいらっしゃることでしょう。なぜ、上記のメソッドが正しく実行できるのでしょうか。ActiveRecord::Baseを継承しただけのクラスに、いつfind_by_hitokotoというメソッドが定義されたのでしょうか。

 種明かしをすると、find_by_hitokotoというメソッドは定義されていません。ActiveRecord::Baseを継承したクラスでは、find_by_というメソッドが呼び出されたとき、find_by_の後ろに書かれた文字列がテーブル中のカラム名であると解釈し、動的にSQLを作成します。ここでは、'hitokoto'をカラム名と解釈し、以下のSQLを発行しています。

SELECT * FROM "hitokotos" WHERE ("hitokotos"."hitokoto" = 'Orange') LIMIT 1

 上記のように動的にメソッド名を解釈するファインダの仕組みを動的ファインダと呼ぶことがあります。動的ファインダを駆使することで、以下のような複雑な検索条件であっても、SQLを意識せずにレコードの抽出が行えます。

>> Hitokoto.find_by_hitokoto_and_created_at("Banana", Time.parse("2009-03-31 05:00:00")
=> #<Hitokoto id: 6, hitokoto: "Banana", created_at: "2009-03-31 05:00:00", updated_at: "2009-03-31 05:00:00">

 また、ファインダメソッドは、上記のような機能に加え、集計条件(GROUP BY句に相当)や、ソート条件(ORDER BY句に相当)などを引数として受け取れます。本稿での説明は割愛しますが、必要に応じてマニュアルや書籍などを参照してみてください。

 
1/3
next

Index
ActiveRecordが提供するModel機能を理解しよう
Page1
ActiveRecordが提供するModel機能
ファインダの動作確認
  Page2
バリデーションの動作確認
  Page3
アソシエーション
マイグレーション

index 3rdRailによるRailsプログラミング入門

 Ruby/Rails関連記事
プログラミングは人生だ
まつもと ゆきひろのコーディング天国
 ときにプログラミングはスポーツであり、ときにプログラミングは創造である。楽しいプログラミングは人生をより実りあるものにしてくれる
生産性を向上させるRuby向け統合開発環境カタログ
Ruby on Rails 2.0も強力サポート
 生産性が高いと評判のプログラミング言語「Ruby」。統合開発環境を整えることで、さらに効率的なプログラミングが可能になる
かんたんAjax開発をするためのRailsの基礎知識
Ruby on RailsのRJSでかんたんAjax開発(前編)
 実はAjaxアプリケーション開発はあなたが思うよりも簡単です。まずはRuby on Railsの基礎知識から学びましょう
Praggerとnetpbmで作る画像→AA変換ツール
Rubyを使って何か面白いものを作ってみよう!
 一般的な画像をアスキーアートに変換するツールを作ってみる。さらに出力にバリエーションを持たせてみよう
コードリーディングを始めよう
Railsコードリーディング〜scaffoldのその先へ〜(1)
 優れたプログラマはコードを書くのと同じくらい、読みこなす。優れたコードを読むことで自身のスキルも上達するのだ
  Coding Edgeフォーラムフィード  2.01.00.91


Coding Edge フォーラム 新着記事
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

>

Coding Edge 記事ランキング

本日 月間