SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

Groovy+GrailsでRailsなWeb開発

Grailsのバリデーションとリレーションシップ

Groovy+GrailsでRailsなWeb開発 第4回

  • X ポスト
  • このエントリーをはてなブックマークに追加

Boardsのindex.gsp

 今度は、hasManyで関連付けているBoardsのindex.gspです。ここでは、各記事へコメントした人の名前をそれぞれ表示させることにしましょう。

<body>
    <h1>Grails Boards</h1>
    <h2>テーブルの一覧リスト</h2>
    <table width="400">
        <g:each in="${tableData}" status="i" var="record">
            <tr>
                <td>${record.id}</td>
                <td>${record.name}</td>
                <td>${record.title}</td>
                <td>
                    <g:each in="${record.comments}" status="j" var="comment">
                        <div style="size:-1;">${comment.name}</div>
                    </g:each>
                </td>
            </tr>
        </g:each>
    </table>
</body>
図6 修正したBoardsのindex画面。タイトルの右側には、それぞれの記事へ投稿した人の名前が表示される。
図6 修正したBoardsのindex画面。タイトルの右側には、それぞれの記事へ投稿した人の名前が表示される。

 ここでは、まず<g:each>を使い、tableDataからBoardsインスタンスを順に取り出して表示をしていきます。コメントをつけた人の名前は、

<g:each in="${record.comments}" status="j" var="comment">

 このようにして繰り返し処理をしています。ここでは、record.commentsとしてrecordのcommentsからインスタンスを取り出しています。commentsというプロパティは、Boardsにはありませんでした。が、hasMany = [comments:Comments]としてhasManyを設定していましたね。これにより、取得されたCommentsインスタンスがcommentsとして設定されていたのです。

 こうしてcommentに取り出したインスタンスから、${comment.name}としてnameの値を取り出し書き出していけば、関連するCommentsのnameをすべて出力できます。

showアクションの作成

 hasManyで関連付けられたレコードの処理がわかったところで、応用例として「特定の投稿と、それへのコメントをまとめて表示する」アクションを作ってみましょう。BoardsControllerにこのようにアクションのクロージャを追加します。

def show = {
    [record:Boards.get(params.id)]
}

 送信されたidパラメータを使ってBoardsからレコードをgetし、それをrecordとしてビューに渡しています。show.gspでは、渡されたrecordをもとに、投稿データと、コメントのデータをそれぞれテーブルにまとめて表示します。

<body>
    <h1>Grails Boards</h1>
    <h2>ID=${record.id}の内容</h2>
    <table width="400">
        <tr width="100"><td>ID</td><td>${record.id}</td></tr>
        <tr><td>名前</td><td>${record.name}</td></tr>
        <tr><td>タイトル</td><td>${record.title}</td></tr>
        <tr><td>内容</td><td>${record.content}</td></tr>
    </table>
    <h3>コメント</h3>
    <table width="400">
        <g:each in="${record.comments}" status="i" var="comment">
            <tr>
                <td width="20">${comment.id}</td>
                <td width="80">${comment.name}</td>
                <td>${comment.message}</td>
            </tr>
        </g:each>
    </table>
</body>
図7 「show?id=番」という形でアクセスすると、その投稿内容と、寄せられたコメントがまとめて表示される。
図7 「show?id=番」という形でアクセスすると、その投稿内容と、寄せられたコメントがまとめて表示される。

 アクセスする際、「show?id=番号」というようにして、表示するID番号を指定すると、Boardsからその番号のレコードを取り出して表示し、さらにその記事へのコメントをComentsからすべて取り出して表示します。コメントは、<g:each>で${record.comments}からインスタンスを順に取り出して処理しています。このように、hasManyやbelongsToを使えば、コントローラー側でただgetして値をビューに渡すだけで、必要なレコードがすべて用意されます。複数レコードを組み合わせた処理が非常に単純な操作で作れることが実感できるでしょう。

まとめ

 今回説明して分かるように、Grailsの場合、バリデーションはレコードの保存とセットで機能します。従って、ドメインクラスと無関係のフォームなどでバリデーションを行う場合には、別途考えなければいけません。今回の説明は、あくまでドメインクラスの保存時のバリデーションと考えてください。

 リレーションシップについては、まずはhasManyとbelongsToによる1対多、多対1の結合を実際に自分で作成して確かめてみるとよいでしょう。Grailsは、リレーションシップはこの2つの組み合わせで実現します。

 従来、こうした結合は、SQLでJOINを用いて行いました。このJOINの考え方にとらわれるあまり、「LEFT JOINに相当する機能は……、INNER JOINは……」と探し回ってしまう人も多いのではないでしょうか。Grailsでは、各JOINごとに対応するリレーションシップが用意されているわけではありません。両者の主従関係からリレーションシップを考えるようにしましょう。

この記事は参考になりましたか?

  • X ポスト
  • このエントリーをはてなブックマークに追加
Groovy+GrailsでRailsなWeb開発連載記事一覧

もっと読む

この記事の著者

掌田 津耶乃(ショウダ ツヤノ)

三文ライター&三流プログラマ。主にビギナーに向けたプログラミング関連の執筆を中心に活動している。※現在、入門ドキュメントサイト「libro」、カード型学習サイト「CARD.tuyano.com」を公開...

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/3916 2009/05/27 14:00

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング