第4回 「つぶやき」アプリを改修してみよう(後編)
富田 陽介
Banana Systems株式会社
2009/4/28
Railsアプリケーション開発を支援する統合開発環境「3rdRail」を使って、開発、デバッグ、プロファイリングの手法をマスターしよう(編集部)
第3回「『つぶやき』アプリを改修してみよう(前編)」では、第1回で作成した「つぶやき」アプリケーションに追加する機能の要件の洗い出しと、その1つである「複数ユーザーによる『ひとこと』を可能にする」の実装とユニットテストを行いました。
今回は、もう1つの要件だった「ユーザーが『ひとこと』を『お気に入り』に登録できるようにする」の実装とユニットテストを行います。
このイテレーションの進め方は、第3回のイテレーションと同様です。前回検討した関連を再確認しましょう。
- User has many Favorites(ユーザーは複数の「お気に入り」を持つ)
- Favorite belongs to User(「お気に入り」は、あるユーザーに属す)
- Hitokoto has many Favorites(「ひとこと」は複数の「お気に入り」を持つ)
- Favorite belongs to Hitokoto(「お気に入り」は、ある「ひとこと」に属す)
この要件を実装するための手順を整理します。
- 新規追加するModelの初期化およびマイグレーション
・Favoriteモデルの追加 - Modelのテストコード実装
・フィクスチャの準備
・以下のテストコードを実装
・Userインスタンスから関連するFavoriteインスタンスを取得
・Favoriteインスタンスから関連するUserインスタンスを取得
・Hitokotoインスタンスから関連するFavoriteインスタンスを取得
・Favoriteインスタンスから関連するHitokotoインスタンスを取得
・Userインスタンスから関連するFavoriteインスタンスを経由し、
関連するHitokotoインスタンスを取得
・Hitokotoインスタンスから関連するFavoriteインスタンスを経由し、
関連するUserインスタンスを取得
・テスト用データベースの準備 - ユニットテスト実行(失敗することを確認)
- 本番コード実装
・2で作成したテストコードが正常に実行できるように実装 - ユニットテスト実行(成功する事を確認)
2でのテストコードが、「複数ユーザーによる『ひとこと』を可能にする」のテストコードよりも多くなっていることにお気付きでしょうか。今回の要件では、Favoriteモデルを中心としたUser、Hitokotoそれぞれへの「一対多」関連を経由し、「多対多」関連を実現します。従って、上記のような複数のテストケースによりこの関連が利用できることを確認します。
Favoriteモデルを追加しよう
Favoriteモデルに必要な属性を検討しましょう。FavoriteモデルはUserとHitokotoの間にある「お気に入り」という関連を示すためだけに存在するモデルです。従って、UserとHitokotoそれぞれに対する関連IDがあれば十分ということになります。
それでは、Favoriteモデルを追加していきます。[Railsエクスプローラー]でtsubuyakiプロジェクト以下の[モデル]を右クリックし、[リソースの新規作成]をクリックします。
モデル名にはfavorite、属性にはuser_idとhitokoto_idを、それぞれinteger型で指定します。それぞれの属性の[必須]列にもチェックを入れておきましょう。[生成されたリソースのスカフォルドを作成する]チェックは外します。
すべて入力が終わったら[完了]を押して、モデルの追加は終わりです。
Favoriteクラスのテストを実装しよう
テストの実装に入っていきましょう。今回作成するFavoriteクラスが持つ関連を確認しておきます。
- User has many Favorites(ユーザーは複数の「お気に入り」を持つ)
- Favorite belongs to User(「お気に入り」は、あるユーザーに属す)
- Hitokoto has many Favorites(「ひとこと」は複数の「お気に入り」を持つ)
- Favorite belongs to Hitokoto(「お気に入り」は、ある「ひとこと」に属す)
それでは、フィクスチャの作成から着手します。Favoriteモデルのサンプルレコードを作成していきましょう。[Railsエクスプローラー]ビューから[テスト]−[フィクスチャー]を選択し、favoritesをダブルクリックしてfavorites.ymlを表示し、編集します。
tomita_banana: id: 1 user_id: 1 hitokoto_id: 1
ここでは、第3回のイテレーションで作成したフィクスチャと対応し、id=1のUserがid=1のHitokotoをお気に入りに登録した、と仮定したサンプルレコードを設定しています。
ユニットテストコードを実装しよう
それでは、関連を利用するためのテストコードを記述します。まず、Favoriteクラスを中心に、User、Hitokoto双方の関連を取得するためのテストコードを書いてみます。[Railsエクスプローラー]の[テスト]−[ユニットテスト]以下からFavoriteをダブルクリックし、favorite_test.rbを開きます。
require 'test_helper' class FavoriteTest < ActiveSupport::TestCase test "Favoriteが属すUserを取得できる" do f = Favorite.find(1) assert f.user == User.find(1) end test "Favoriteが属すHitokotoを取得できる" do f = Favorite.find(1) assert f.hitokoto == Hitokoto.find(1) end end
このテスト内容は、testメソッドに渡している引数文字列が示すとおりですので、詳細を割愛します。
同様に、user_test.rbとhitokoto_test.rbを以下のとおり編集し、テストを追加していきましょう。なお、上記2つのテストスクリプトに含まれる、第3回のイテレーションで使用したテストを削除しないように注意しましょう。
require 'test_helper' class UserTest < ActiveSupport::TestCase test "Userに属すHitokotoを取得できる" do u = User.find(1) assert u.hitokotos == Hitokoto.find_all_by_user_id(1) end test "Userに属すFavoriteを取得できる" do u = User.find(1) assert u.favorites == Favorite.find_all_by_user_id(1) end test "UserからFavoriteモデルを経由して、関連するHitokotoを取得できる" do u = User.find(1) assert u.favorite_hitokotos == [Hitokoto.find(1)] end end
require 'test_helper' class HitokotoTest < ActiveSupport::TestCase test "Hitokotoが属すUserを取得できる" do h = Hitokoto.find(1) assert h.user == User.find(1) end test "Hitokotoに属すFavoriteを取得できる" do h = Hitokoto.find(1) assert h.favorites == Favorite.find_all_by_hitokoto_id(1) end test "HitokotoからFavoriteモデルを経由して、関連するUserを取得できる" do h = Hitokoto.find(1) assert h.favorited_users == [User.find(1)] end end
さて、ここで追加したテスト内容も、testメソッドに渡している引数文字列が示すとおりですが、各ファイル最後のテストについて確認しておきましょう。
例えば、user_test.rbでは、以下の行により「該当のユーザーがお気に入りに登録している『ひとこと』」を取得しようとしています。
u.favorite_hitokotos
同様に、以下の行では「該当の『ひとこと』をお気に入りに登録しているユーザー」を取得しようとしています。
h.favorited_users
これらのメソッドはどこで定義されるのでしょうか。そもそも、ActiveRecordのアソシエーション機能で、上記のような「多対多」関連を簡単に取得できるのでしょうか。
先に結論だけ述べます。ActiveRecordは上記のような「多対多」関連であっても、簡単に解決する方法を提供しています。実際にどのように書けばよいのかについては、後述します。まずは、上記で作成したユニットテストを実行し、新しく追加したテストが失敗することを確認しましょう。
テスト用データベースをマイグレーションしよう
第3回と同様に、テスト用データベースの準備をしましょう。[プロジェクトコマンダー]で以下のコマンドを実行し、テスト用データベースのマイグレーションを実行します。
> rake db:test:prepare
以上で、テスト用データベースの準備は完了です。
1/2 |
Index | |
「つぶやき」アプリを改修してみよう(後編) | |
Page1 Favoriteモデルを追加しよう Favoriteクラスのテストを実装しよう ユニットテストコードを実装しよう テスト用データベースをマイグレーションしよう |
|
Page2 ユニットテスト実行を実行しよう Modelの本番コードを実装しよう Modelクラスの開発ステップのまとめ |
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を紹介する。※ショートカットキー、アクセスキーの解説あり
|
|