Grails をマスターする: Groovy Server Pages によるビューの変更

GSP (Groovy Server Pages) は、Grails Web フレームワークの Web の部分になります。連載「Grails をマスターする」の第 3 回目では、Scott Davis が GSP の操作について詳細に説明します。Grails TagLib は簡単に使用できること、そして GSP のコード・フラグメントを組み合わせたり、scaffold により自動的に生成されるビューのデフォルト・テンプレートをカスタマイズしたりするのも簡単であるということを学んでください。

Scott Davis , Editor in Chief, AboutGroovy.com

Scott DavisScott Davis は国際的に知られた著者、講演者、そしてソフトウェア開発者です。彼の著書には、『Groovy Recipes: Greasing the Wheels of Java』、『GIS for Web Developers: Adding Where to Your Application』、『The Google Maps API』、『JBoss At Work』などがあります。



2008年 3月 11日

この連載の最初の 2 回の記事では、Grails Web フレームワークの基本的なビルディング・ブロックを紹介しました。そのなかで何度も繰り返しましたが、Grails がベースとするのはモデル・ビュー・コントローラー (MVC) アーキテクチャー・パターン (「参考文献」を参照) で、Grails は「Convention over Configuration (設定より規約)」を優先してフレームワークの部品を組み合わせます。従来の方法ではこれらのリンクの一覧を手動で外部構成ファイルに作成しましたが、このエラーの原因となりがちな古い方法に代わり、Grails では直観的な名前を付けたファイルとディレクトリーを使用します。例えば第 1 回目の記事で説明したように、コントローラーには Controller というサフィックスが付けられ、その保存場所は grails-app/controller ディレクトリーとなります。また第 2 回では、ドメイン・モデルは grails-app/domain ディレクトリーにあることを説明しました。

今月は MVC 三部作の締めくくりとして、Grails のビューを取り上げます。ご想像のとおり、ビューが保存されるのは grails-app/views ディレクトリーです。しかしビューにまつわる話は、ディレクトリー名が直感的に明らかであるという話だけではなく、他にもさまざまな話があります。そこで、今回は GSP (Groovy Server Pages) について説明し、さらに GSP の他にも数多くあるビューの選択肢に関するアドバイスをします。この記事では、標準 Grails タグ・ライブラリー (TagLib) の概要について、そして独自の TagLib をいかに簡単に作成できるかを学びます。また、GSP コードの共通フラグメントの要素を独自の部分テンプレートへと分解することによって、DRY (Don’t Repeat Yourself、「参考文献」を参照) のための継続的な戦いに取り組む方法についても説明します。そして最後に、scaffold によって生成されるビューのデフォルト・テンプレートを調整し、それによって自動的に作成されるビューの利便性と Grails アプリケーションが持つデフォルトのルック・アンド・フィールをカスタマイズしたいという要求とのバランスを取る方法も学んでください。

Grails アプリケーションの表示

この連載について

Grails は、Spring や Hibernate などのよく知られた Java 技術に「Convention over Configuration」といった現代のプラクティスを盛り込んだ最新の Web 開発フレームワークです。Groovy で作成された Grails は既存の Java コードをシームレスに統合するだけでなく、スクリプト言語ならではの柔軟性と動的機能を与えてくれます。Grails を学んだら、Web 開発に対する今までの見方がまったく違ってくるはずです。

Grails がプレゼンテーション層として使用するのは GSP です。GSP の Groovy は基礎となる技術だけでなく、簡単なスクリプトレットを作成する場合に使用可能な言語も識別します。そういった意味では、Java コードの断片を Web ページに混在させられる JSP (Java™Server Pages) 技術や、HTML タグの間に Ruby の断片を忍び込ませることのできる RHTML (Ruby on Rails のコアとなるビュー技術) とよく似ています。

もちろんスクリプトレットは長い間、Java コミュニティーでは冷ややかな目を向けられてきました。スクリプトレットは技術を最も再利用 (コピー・アンド・ペースト) しにくい形にするだけでなく、他にも技術的に好ましくない行為をもたらすからです (使用できるから使用するのと、使用すべきであるから使用するというのには大きな違いがあります)。GSP の G は本来、洗練されていて正直な Java 市民に実装言語だけを連想させるものでなければなりません。Groovy の TagLib と部分テンプレートは、Web ページ間でコードと振る舞いを共有する一層高度な方法となります。

GSP は、Grails が持っている、ページを中心とした MVC の世界のビューの基礎となります。この場合、あらゆる手段の基本単位となるのはページです。List ページには Show ページへのリンクが提供されており、Show ページではクリックすることによって Edit ページが表示される、といった具合です。経験豊かな Struts 開発者であろうと、Rails の支持者に最近なった人であろうと、このような Web のライフサイクルはすでにお馴染みのはずです。

このことをわざわざ持ち出したのは、この数年間、ページ中心ではないビュー技術が爆発的に増えているからです (「参考文献」を参照)。その筆頭としては JSF (JavaServer Faces) や Tapestry などのコンポーネント指向の Web フレームワークが挙げられます。また、Ajax 革命が Dojo や YUI (Yahoo! UI) ライブラリーをはじめとする数々の JavaScript ベースのソリューションを生み出しています。Adobe Flash や GWT (Google Web Toolkit) などのリッチ・インターネット・アプリケーション (RIA) プラットフォームは、一層リッチでデスクトップのようなユーザー・エクスペリエンスによって Web デプロイメントの利便性を約束しています。幸いなことに、Grails ではこのようなビュー技術のすべてを容易に操作することができます。

MVC によってコンサーン (関心事) を分離するということの本質は、Web アプリケーションをどんなビュー技術を使っても簡単に表示できるようにするということです。Grails のプラグイン・インフラストラクチャーに人気があるのは、GSP の代わりとなるさまざまなプラグインを単に grails install-plugin を実行するだけで使えるからです (使用可能なプラグインの全リストは「参考文献」に記載したリンクを参照するか、またはコマンド・プロンプトに grails list-plugins と入力して表示してください)。プラグインの多くはコミュニティーが主導するもので、プレゼンテーション層技術として Grails を使いたいという人々によって生まれました。

Grails には JSF を対象とした、Grails に固有の自動フックはありませんが、この 2 つを同時に使用することを妨げるものは何もありません。Grails アプリケーションは標準 Java EE アプリケーションです。そのため、適切な JAR を lib ディレクトリーに配置して WEB-INF/web.xml 構成ファイルに該当する設定を追加することで、いつもと同じようにアプリケーションを作成することができます。Grails アプリケーションは標準サーブレット・コンテナーの中でデプロイされるので、Grails は GSP と同じく JSP もサポートします。また、Grails プラグインは Echo2 および Wicket (どちらもコンポーネント指向の Web フレームワーク) を対象としているため、JSF あるいは Tapestry プラグインの障害となるものは一切ありません。

同様に、Dojo や YUI などの Ajax フレームワークを Grails に追加する手順も通常とまったく同じで、JavaScript ライブラリーを web-app/js ディレクトリーにコピーするだけです。Prototype と Scriptaculous はデフォルトで Grails と一緒にインストールされます。RichUI プラグインは最善の手法を使って、さまざまな Ajax ライブラリーから UI ウィジェットを選択します。

プラグインのリストを一通り見てみると、Flex、OpenLazlo、GWT、ZK などといった RIA クライアントがサポートされることに気付くはずです。このように、Grails アプリケーションには GSP の代わりとなるビュー・ソリューションが豊富にあることは確かですが、まずは Grails が追加設定なしでサポートするネイティブ・ビュー技術である GSP についての詳細を説明しておきます。


GSP の基本

GSP ページを見分ける方法は何通りかあります。.gsp というファイル拡張子が付いていれば、それが決定的証拠になります。また、<g: で始まるタグが大量に使用されている場合も、GSP ページである証拠です。実際のところ、GSP ページとは動的コンテンツ用の Grails タグが混ざった標準 HTML に過ぎません。前のセクションで取り上げた GSP の代わりとなるビュー技術のうち、一部は HTML、CSS、そして JavaScript の詳細を Java や ActionScript、あるいはその他のプログラミング言語レイヤーの背後に隠す不透明な抽象化レイヤーです。GSP は標準 HTML を覆う薄い Groovy のファサードであるため、ネイティブ Web 技術を使う必要があると思ったときには、いつでも簡単にフレームワークから剥がし取ることができます。

ただし現時点の Trip Planner アプリケーションでは、そう簡単には GSP を見つけられないでしょう (Trip Planner アプリケーションのビルド手順については連載の最初の 2 回の記事で説明しています。この手順にまだ従っていない場合は、ここで手順に従っておくことをお勧めします)。今のところ、ビューには動的に生成される scaffold を使用しているので trip-planner/grails-app/views ディレクトリーは空です。動的に scaffold を生成するためのコマンドを確認するには、テキスト・エディターで grails-app/controller/TripController.groovy (リスト 1 に記載) を開いてください。

リスト 1. TripController クラス
class TripController{
  def scaffold = Trip
}

def scaffold = Trip の行によって、Grails には実行時に動的に GSP を生成するように指示がされます。この方法は、ドメイン・モデルが変更されても自動的にビューを同期させるには素晴らしい方法ですが、フレームワークについて学ぼうとしているときには、この設定ではあまり意味がありません。

trip-planner ディレクトリーのルートで grails generate-all Trip を実行し、既存のコントローラーをオーバーライドするかどうかを尋ねられたら y と答えてください (a と答えてすべてをオーバーライドし、繰り返しプロンプトが出されないようにすることもできます)。すると、(数あるクロージャーの中でも) create、edit、list、そして show といったクロージャーを持つ完全な TripController クラスが表示されます。さらに、grails-app/views/trip ディレクトリーには create.gsp、edit.gsp、list.gsp、show.gsp という 4 つの GSP も生成されているはずです。

ここで登場するのが「Convention over Configuration」です。http://localhost:9090/trip-planner/trip/list にアクセスするときには、TripControllerTrip ドメイン・モデル・オブジェクトのリストを設定させ、さらにこのリストを trip/list.gsp ビューに渡すように指示していることになります。テキスト・エディターでもう一度、TripController.groovy (リスト 2 に記載) を確認してみてください。

リスト 2. 完全にデータが設定された TripController クラス
class TripController{
  ...
  def list = {
    if(!params.max) params.max = 10
    [ tripList: Trip.list( params ) ]
  }
  ...
}

この短いクロージャーはデータベースから 10 件の Trip レコードを取得し、それらのレコードを POGO に変換してから tripList という ArrayList に保存します。すると list.gsp ページがリスト全体で繰り返し処理を行い、HTML の表を 1 行ごとに作成します。

次のセクションでは、Web ページにそれぞれの Trip を表示するための <g:each> タグをはじめ、よく使われるさまざまな Grails タグを取り上げて説明します。


Grails のタグ

<g:each> は一般的に使用される Grails のタグで、リスト内の各項目を繰り返し処理します。このタグの使い方を確認するには、テキスト・エディターで grails-app/views/trip/list.gsp (リスト 3 に記載) を開いてください。

リスト 3. list.gsp ビュー
<g:each in="${tripList}" status="i" var="trip">
  <tr class="${(i % 2) == 0 ? 'even' : 'odd'}">
    <td><link action="show" id="${trip.id}">${trip.id?.encodeAsHTML()}</g:link></td>
    <td>${trip.airline?.encodeAsHTML()}</td>
    <td>${trip.name?.encodeAsHTML()}</td>
    <td>${trip.city?.encodeAsHTML()}</td>
    <td>${trip.startDate?.encodeAsHTML()}</td>
    <td>${trip.endDate?.encodeAsHTML()}</td>
  </tr>
</g:each>

<g:each> タグに含まれる status 属性は単純なカウンター・フィールドです (次の行では、CSS スタイルを even または odd に設定する 3 項演算子でこの値が使用されていることに注意してください)。var 属性では、現行の項目を保持するための変数に名前を付けることができます。この名前を foo に変更する場合は、以降の行もそれに従って ${foo.airline?.encodeAsHTML()}のように変更しなければなりません (?.演算子は NullPointerException を避けるための Groovy の方法で、例えば「airline がヌルでない場合にだけ encodeAsHTML() メソッドを呼び出し、ヌルの場合には単に空のストリングを返す」ことを簡単明瞭に表現しています)。

<g:link> も、よく使われる Grails のタグの 1 つです。もうお気付きかもしれませんが、このタグは HTML の <a href> リンクを作成します。<a href> タグをそのまま使用することももちろんできますが、この便利なタグは actionidcontroller などの属性を受け入れます。周りを囲む anchor タグ抜きで href 値だけを処理したい場合には、代わりに <g:createLink> を使用することもできます。list.gsp の先頭にはリンクを返す 3 番目のタグ、<g:createLinkTo> があるはずです。このタグは論理 controlleractionid 属性ではなく dir 属性と file 属性を受け入れます。リスト 4 に、linkcreateLinkTo が使われている様子を示します。

リスト 4. link タグと createLinkTo タグ
<div class="nav">
  <span class="menuButton"><a class="home" href="${createLinkTo(dir:'')}">Home</a></span>
  <span class="menuButton"><link class="create" action="create">New Trip</g:link></span>
</div>

リスト 4 で注目してもらいたいことは、Grails のタグを呼び出すには不等号括弧内のタグ、あるいは中括弧内のメソッド呼び出しという 2 つの形式を交互に使えるという点です。メソッド呼び出しが別のタグの属性に組み込まれている場合には、中括弧の表記 (正式な名称は EL (Expression Language: 式言語) 構文) のほうが適しています。

list.gsp で数行下を見ると、よく使われるもう 1 つの Grails タグ、<g:if> (リスト 5 に記載) もあります。以下の例の場合、このタグが指定しているのは「flash.message 属性がヌルでない場合は表示する」という内容です。

リスト 5. <g:if> タグ
<h1>Trip List</h1>
<if test="${flash.message}">
  <div class="message">${flash.message}</div>
</g:if>

生成されたビューを一通り見てみると、他にも多くのタグが使われていることに気付くはずです。例えば、<g:paginate> タグは現在表示されている 10 件を超える Trip がデータベースに含まれている場合には「previous (前へ)」と「next (次へ)」のリンクを表示します。<g:sortable> タグはソートするために列のヘッダーをクリックできるようにします。また、他の GSP ページをいろいろと見てみると、<g:form><g:submit> などの HTML フォーム関連のタグもあります。使用できるすべての Grails タグと、それぞれの使用例は Grails のオンライン・マニュアルに記載されています (「参考文献」を参照)。


カスタム・タグ・ライブラリー

Grails の標準的なタグはかなり役に立ちますが、いずれは独自のカスタム・タグが必要な状況に出くわすことでしょう。経験を積んだ多くの Java 開発者 (私を含め) は「この場合に適切なアーキテクチャー・ソリューションはカスタム TagLib を使うことだ」と公言しながらも、誰も見ていないとわかれば、こっそりスクリプトレットを作成しています。カスタム JSP TagLib の作成には大変な労力が伴うため、スクリプトレットが最も楽な道として選ばれるわけです。スクリプトレットは適切な手段ではありませんが、(不幸にも) 簡単な手段であることは確かです。

スクリプトレットという言葉の意味を厳密に捉えると、それは何かを取り込むことです。スクリプトレットは HTML のタグをベースとしたパラダイムを崩し、生のコードをそのままビューに取り込みます。コードを取り込むこと自体のみならず、カプセル化と再利用の可能性がないことも問題です。スクリプトレットを再利用するには、コピー・アンド・ペーストするしかありません。しかし、それによってバグ、コードの膨張、そしてあからさまな DRY 違反につながります。これだけでも十分問題なのに、さらにスクリプトレットにはテストしにくいという問題まであります。

そうは言っても、私は締め切りに迫られると、かなりの量の JSP スクリプトレットを作成していたと告白しなければなりません。JSTL (JSP Standard Tag Library) が私を誘惑から救い出す上で大きな役割を果たしましたが、独自のカスタム JSP タグを作成することとはまるで別の問題です。カスタム JSP タグを Java コードで作成してコンパイルし、TLD (Tag Library Descriptor) を適切なフォーマットで適切な場所に配置するようにいじり回すなかで、タグを作成するそもそもの理由をすっかり忘れていました。しかし、新しい JSP タグを検証するためのテストを作成するという点では、私の意図は正しかったと言っておきましょう。

それとは対照的に、Grails でカスタム TagLib を作成するのはいとも簡単です。このフレームワークはテストの作成をはじめとし、正しいことを簡単に行えるようにしてくれます。一例として、私の Web ページには通常、下端に定形文の著作権情報を載せなければなりません。この情報は © 2002 - 2008, FakeCo Inc. All Rights Reserved となりますが、ここで 1 つ困ったことがあります。それは、2 番目に来ている年が常に現在の年になるようにしなければならないということです。リスト 6 に、スクリプトレットでの方法を示します。

リスト 6. スクリプトレットによる著作権情報
<div id="copyright">
&copy; 2002 - ${Calendar.getInstance().get(Calendar.YEAR)}, 
    FakeCo Inc. All Rights Reserved.
</div>

現在の年を取り込む方法がわかったところで、次はこれと同じことを行うカスタム・タグを作成します。まずは grails create-tag-lib Date と入力してください。これによって、grails-app/taglib/DateTagLib.groovy (TagLib) と grails-app/test/integration/DateTagLibTests.groovy (テスト) という 2 つのファイルが作成されるので、DateTagLib.groovy ファイルのほうにリスト 7 のコードを追加します。

リスト 7. 単純なカスタム Grails タグ
class DateTagLib {
  def thisYear = {
    out << Calendar.getInstance().get(Calendar.YEAR)
  }
}

リスト 7 は <g:thisYear> タグを作成します。ご覧のように、年は出力ストリームに直接書き込まれます。リスト 8 に、この新しいタグが使われている様子を示します。

リスト 8. カスタム・タグによる著作権情報
<div id="copyright">
&copy; 2002 - <g:thisYear />, FakeCo Inc. All Rights Reserved.
</div>

これで作業は完了したと思うかもしれませんが、恐縮なことに、まだ半分しか終わっていません。


TagLib のテスト

今のところ万事順調のように見えても、このタグが将来壊れないことを確認するためのテストは作成しなければなりません。「Working Effectively with Legacy Code」の著者である Michael Feathers は、テストのないコードはいずれもレガシー・コードであると言っています。Feathers 氏から叱咤されることのないように、DateTagLibTests.groovy ファイルにリスト 9 のコードを追加してください。

リスト 9. カスタム・タグのテスト
class DateTagLibTests extends GroovyTestCase {
  def dateTagLib

  void setUp(){
    dateTagLib = new DateTagLib()
  }

  void testThisYear() {
    String expected = Calendar.getInstance().get(Calendar.YEAR)
    assertEquals("the years don't match", expected, dateTagLib.thisYear())
  }
}

GroovyTestCase は JUnit 3.x TestCase の上にある薄い Groovy のファサードです。単純な 1 行のタグのためにテストを作成するのは、やり過ぎのように思えるかもしれませんが、たった 1 行が問題の原因となる場合がいかに多いかを知れば驚くはずです。テストは簡単に作成できるため、あとで後悔するよりは今用心しておくに越したことはありません。grails test-app と入力してこのテストを実行してください。すべてが上手く行くと、リスト 10 のメッセージが表示されるはずです。

リスト 10. Grails でのテスト合格
-------------------------------------------------------
Running 2 Integration Tests...
Running test DateTagLibTests...
                    testThisYear...SUCCESS
Running test TripTests...
                    testSomething...SUCCESS
Integration Tests Completed in 506ms
-------------------------------------------------------

TripTests の出現が予想外だとしても、心配には及びません。grails create-domain-class Trip と入力したときに、テストが自動的に生成されたからです。実際、Grails の create コマンドを実行するたびに、対応するテストが生成されます。最近のソフトウェア開発では、テストはそれだけ重要だということです。テストを作成する習慣がまだ身についていないのであれば、Grails に従って徐々に正しい方向に向かってください。決して後悔しないはずです。

grails test-app コマンドはテストを実行する他、わかりやすい HTML レポートも作成します。ブラウザーで test/reports/html/index.html を開くと、図 1 に示す標準 JUnit テスト・レポートを確認できます。

図 1. ユニット・テスト・レポート
ユニット・テスト・レポート

これで単純なカスタム・タグのコーディングとテストは完了したので、今度はもう少々高度なタグを作成してみます。


高度なカスタム・タグ

より高度なタグになると、属性とタグ本体を操作できるようになります。例えば、現時点での著作権のソリューションには、まだあまりにも多くのコピー/ペースト作業が必要です。そこで、現行の振る舞いをすべて、<g:copyright startYear="2002">FakeCo Inc.</g:copyright> のような実際に再利用可能なタグにラップすることにします。このコードはリスト 11 のとおりです。

リスト 11. 属性と本体の操作を行う Grails タグ
class DateTagLib {
  def thisYear = {
    out << Calendar.getInstance().get(Calendar.YEAR)
  }

  def copyright = { attrs, body ->
    out << "<div id='copyright'>"
    out << "&copy; ${attrs['startYear']} - ${thisYear()}, ${body()}"
    out << " All Rights Reserved."
    out << "</div>"
  }
}

attrs はタグ属性の HashMap であることに注目してください。ここでは startYear 属性を取得するために使っています。thisYear タグはクロージャーとして呼び出しています (このクロージャー呼び出しは、中括弧内の GSP ページからクロージャーを呼び出すことにした場合と同じです)。同様に、body もクロージャーとしてタグに渡すので、他のタグを呼び出す場合と同じ方法で呼び出しています。このようにすると、カスタム・タグを GSP の任意の深さまで確実にネストすることができます。

もうお気付きかもしれませんが、カスタム TagLib は標準 Grails TagLib と同じ g: 名前空間を使用します。TagLib をカスタム名前空間に配置する場合には、static namespace = 'trip' を DateTagLib.groovy に追加してください。すると、GSP での TagLib は <trip:copyright startYear="2002">FakeCo Inc.</trip:copyright> となるはずです。


部分テンプレート

カスタム・タグは、コピー/ペーストしたスクリプトレットとなってしまうような短いコード・スニペットを再利用可能にする優れた手段です。その一方で、GSP マークアップのブロックが大きい場合には、部分テンプレートを使用することができます。

Grails のマニュアルでは、部分テンプレートの正式名称はテンプレートとなっています。ここで 1 つ問題となるのは、Grails ではテンプレートという用語にさまざまな意味が詰め込まれているという点です。次のセクションを読むとわかるように、scaffold によって生成されるビューを変更するには、デフォルト・テンプレートをインストールすることになります。デフォルト・テンプレートに対して加える変更のなかには、これから説明する部分テンプレートを含めることができます。混乱を少なくするため、ここでは Rails コミュニティーでの用語を借りて、単にテンプレートと呼ぶ代わりに部分テンプレートと呼ぶことにします。

部分テンプレートとは、複数の Web ページで共有することができる GSP コードの塊のことです。一例として、すべてのページで標準フッターを使用するために、_footer.gsp という名前の部分テンプレートを作成するとします。名前の先頭のアンダーバーは、フレームワークにこれが完全な整形式 GSP ではないことを示唆するためのものです (開発者にとっては視覚的な手掛かりになります)。このファイルを grails-app/views/trip ディレクトリーに作成したとすると、Trip ビューにしか表示されません。そこで、ファイルを grails-app/views ディレクトリーに保存して、すべてのページがグローバルに共有できるようにします。リスト 12 は、グローバルに共有されるフッターの部分テンプレートです。

リスト 12. Grails の部分テンプレート
<div id="footer">
  <g:copyright startYear='2002'>FakeCo, Inc.</g:copyright>

  <div id="powered-by">
    <img src="${createLinkTo(dir:'images', file:'grails-powered.jpg')}" />
  </div>
</div>

ご覧のように、部分テンプレートでは HTML/GSP 構文で内容を表現することができますが、その一方、カスタム TagLib は Groovy で作成されます。この 2 つの点をわかりやすく言い換えると、通常、細かな振る舞いをカプセル化するには TagLib のほうが適している一方、レイアウト要素を再利用するには部分テンプレートのほうが適しているということになります。

上記の例を作成したとおりに機能させるには、「Powered by Grails」ボタンを grails-app/web-app/images ディレクトリーにダウンロードする必要があります (「参考文献」を参照)。このダウンロード・ページには、高解像度のロゴから 16x16 のファビコンに至るまで多彩な Grails 商標が用意されています。

新しく作成したフッターを list.gsp ページの下端に組み込む方法は、リスト 13 を見るとわかります。

リスト 13. 部分テンプレートのレンダリング
<html><body>
...
<g:render template="/footer" />
</body></html>

テンプレートをレンダリングする際にはアンダーバーを省くことに注意してください。_footer.gsp を trip ディレクトリーに保存した場合は、先頭のスラッシュも同じく省くことになります。つまり、grails-app/views ディレクトリーがビュー階層のルートであると考えればよいわけです。


デフォルトの scaffold のカスタマイズ

テストも再利用も可能な優れたコンポーネントが用意できたところで、次はこれらのコンポーネントをデフォルトの scaffold の一部にします。scaffold は、def scaffold = Foo をコントローラーに配置すると自動的に生成されることを思い出してください。さらに、デフォルトの scaffold は grails generate-views Trip または grails generate-all Trip と入力すると作成される GSP のソースにもなっています。

デフォルトの scaffold をカスタマイズするには、grails install-templates と入力します。これによってプロジェクトに新しく grails-app/src/templates ディレクトリーが追加され、artifacts、scaffolding、war という名前の 3 つのディレクトリーが作成されます。

artifacts ディレクトリーには、ControllerDomainClassTagLib をはじめとするさまざまな Groovy クラスのテンプレートが保持されます。例えば、コントローラーのすべてに抽象親クラスを継承させる場合、このディレクトリーでその変更を行うと、新しいコントローラーはいずれも変更されたテンプレート・コードに基づくことになります (人によっては def scaffold = @artifact.name@ を追加して、動的な scaffold の生成をすべてのコントローラーのデフォルトの振る舞いにします)。

war ディレクトリーには、すべての Java EE 開発者にお馴染みの web.xml ファイルが含まれています。独自のパラメーター、フィルター、あるいはサーブレットを追加する必要があれば、このファイルに追加します (JSF 支持者の皆さん、この点をしっかり心に留めておいてください)。grails war と入力すると、このディレクトリーに配置された web.xml ファイルが結果として作成される WAR に組み込まれます。

scaffolding ディレクトリーに含まれるのは、動的に生成されるビューの素材です。list.gsp を開いて、このファイルの最後に <render template="/footer" /> を追加してください。これらのテンプレートはすべてのビューで共有されるため、必ずグローバル部分テンプレートを使用するようにします。

これで、List ビューのカスタマイズは終わったので、次はこれまでに行った変更が有効になっていることを確認します。デフォルト・テンプレートに対する変更は、サーバーの再起動が必要となる数少ない場合の 1 つです。Grails が再起動したら、ブラウザーで http://localhost:9090/trip-planner/airline/list にアクセスしてみてください。AirlineController でデフォルトの scaffold が使用されている場合には、ページの下端に新しいフッターが表示されるはずです。


まとめ

連載「Grails をマスターする」の最終回の内容は、以上ですべてです。今回の記事で、GSP の詳細、そして Grails で Grails の代わりに使用できるビュー技術について理解していただけたと思います。また、生成されたページの多くで使用されるデフォルト・タグについても理解が深まったはずです。スクリプトレットを作成する代わりにカスタム TagLib を作成することで、簡単に正しい方法を実践できることがわかった今、次にスクリプトレットを作成するときには多少の後ろめたさを感じることでしょう。さらにこの記事では、部分テンプレートを作成する方法を説明し、デフォルトで scaffold によって生成されるビューに部分テンプレートを追加するのは至って簡単であることも実演してみせました。

来月の Grails の Web フレームワークのツアーでは、Ajax に焦点を当てます。ページ全体をリロードせずに「ちょっとした」 HTTP リクエストを行えることが、Google Maps や Flickr、それにその他の多くの Web サイトの人気を支えている秘訣ですが、それと同じ魔法をほんの少し Grails でも使用できるようにします。具体的には、多対多の関係を作成し、Ajax を使用してユーザー・エクスペリエンスを自然で楽しいものにするという内容です。

それまではどうぞ、Grails のマスターに励んでください。

参考文献

学ぶために

製品や技術を入手するために

  • Grails: Grails の最新リリースをダウンロードしてください。
  • Powered by Grails」ボタン: この記事のサンプル・アプリケーションに必要です。

議論するために

コメント

developerWorks: サイン・イン

必須フィールドは(*)で示されます。


IBM ID が必要ですか?
IBM IDをお忘れですか?


パスワードをお忘れですか?
パスワードの変更

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


お客様が developerWorks に初めてサインインすると、お客様のプロフィールが作成されます。会社名を非表示とする選択を行わない限り、プロフィール内の情報(名前、国/地域や会社名)は公開され、投稿するコンテンツと一緒に表示されますが、いつでもこれらの情報を更新できます。

送信されたすべての情報は安全です。

ディスプレイ・ネームを選択してください



developerWorks に初めてサインインするとプロフィールが作成されますので、その際にディスプレイ・ネームを選択する必要があります。ディスプレイ・ネームは、お客様が developerWorks に投稿するコンテンツと一緒に表示されます。

ディスプレイ・ネームは、3文字から31文字の範囲で指定し、かつ developerWorks コミュニティーでユニークである必要があります。また、プライバシー上の理由でお客様の電子メール・アドレスは使用しないでください。

必須フィールドは(*)で示されます。

3文字から31文字の範囲で指定し

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


送信されたすべての情報は安全です。


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=60
Zone=Java technology, Web development
ArticleID=302348
ArticleTitle=Grails をマスターする: Groovy Server Pages によるビューの変更
publish-date=03112008