第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
サンプルデータが登録できたら、アプリケーションサーバは停止しておきましょう。ウィンドウ下部の[サーバー]タブから、始動済みになっているサーバを右クリックして[停止]を選択すれば、アプリケーションサーバを停止できます。
ファインダの動作確認
それでは、ActiveRecordにより定義されているファインダの機能を使用し、データベースから先ほど登録したサンプルデータを取り出してみましょう。
動作確認には、3rdRailのRailsコンソール機能を使用します。3rdRailのメニューから、[ウィンドウ]−[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 |
Index | |
ActiveRecordが提供するModel機能を理解しよう | |
Page1 ActiveRecordが提供するModel機能 ファインダの動作確認 |
|
Page2 バリデーションの動作確認 |
|
Page3 アソシエーション マイグレーション |
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) 優れたプログラマはコードを書くのと同じくらい、読みこなす。優れたコードを読むことで自身のスキルも上達するのだ |
|
- プログラムの実行はどのようにして行われるのか、Linuxカーネルのコードから探る (2017/7/20)
C言語の「Hello World!」プログラムで使われる、「printf()」「main()」関数の中身を、デバッガによる解析と逆アセンブル、ソースコード読解などのさまざまな側面から探る連載。最終回は、Linuxカーネルの中では、プログラムの起動時にはどのような処理が行われているのかを探る - エンジニアならC言語プログラムの終わりに呼び出されるexit()の中身分かってますよね? (2017/7/13)
C言語の「Hello World!」プログラムで使われる、「printf()」「main()」関数の中身を、デバッガによる解析と逆アセンブル、ソースコード読解などのさまざまな側面から探る連載。今回は、プログラムの終わりに呼び出されるexit()の中身を探る - VBAにおけるFileDialog操作の基本&ドライブの空き容量、ファイルのサイズやタイムスタンプの取得方法 (2017/7/10)
指定したドライブの空き容量、ファイルのタイムスタンプや属性を取得する方法、FileDialog/エクスプローラー操作の基本を紹介します - さらば残業! 面倒くさいエクセル業務を楽にする「Excel VBA」とは (2017/7/6)
日頃発生する“面倒くさい業務”。簡単なプログラミングで効率化できる可能性がある。本稿では、業務で使うことが多い「Microsoft Excel」で使えるVBAを紹介する。※ショートカットキー、アクセスキーの解説あり
|
|