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

第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(「お気に入り」は、ある「ひとこと」に属す)

 この要件を実装するための手順を整理します。

  1. 新規追加するModelの初期化およびマイグレーション
     ・Favoriteモデルの追加
  2. Modelのテストコード実装
     ・フィクスチャの準備
     ・以下のテストコードを実装
      ・Userインスタンスから関連するFavoriteインスタンスを取得
      ・Favoriteインスタンスから関連するUserインスタンスを取得
      ・Hitokotoインスタンスから関連するFavoriteインスタンスを取得
      ・Favoriteインスタンスから関連するHitokotoインスタンスを取得
      ・Userインスタンスから関連するFavoriteインスタンスを経由し、
       関連するHitokotoインスタンスを取得
      ・Hitokotoインスタンスから関連するFavoriteインスタンスを経由し、
       関連するUserインスタンスを取得
     ・テスト用データベースの準備
  3. ユニットテスト実行(失敗することを確認)
  4. 本番コード実装
     ・2で作成したテストコードが正常に実行できるように実装
  5. ユニットテスト実行(成功する事を確認)

 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を表示し、編集します。

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を開きます。

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回のイテレーションで使用したテストを削除しないように注意しましょう。

user_test.rb
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
hitokoto_test.rb
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
next

Index
「つぶやき」アプリを改修してみよう(後編)
Page1
Favoriteモデルを追加しよう
Favoriteクラスのテストを実装しよう
ユニットテストコードを実装しよう
テスト用データベースをマイグレーションしよう
  Page2
ユニットテスト実行を実行しよう
Modelの本番コードを実装しよう
Modelクラスの開発ステップのまとめ

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 記事ランキング

本日 月間