Grails をマスターする: Grails アプリケーションの見栄えを良くする

アプリケーションのルック・アンド・フィールを CSS、テンプレート、タグ、タグ・ライブラリーなどを使って変更する

連載「Grails をマスターする」の今回の記事では、Scott Davis が CSS (Cascading Style Sheets)、テンプレート、タグ・ライブラリー (TagLib) などを駆使して Grails アプリケーションのルック・アンド・フィールを一新させる方法を実演します。

2 年目の連載「Grails をマスターする」にようこそ。2008年の最後の記事でお約束したとおり、新たな年は新たなアプリケーションで迎えるべく、Trip Planner に代わって新ブログ公開システムが登場します。

新しいアプリケーションには、Blogito という名前を付けました。これはスペイン語で「簡易的なブログ」を意味する一方、デカルトの Cogito ergo sum (我思う、故に我あり) に敬意を表した名前でもあります。アプリケーションの完成版は、blogito.org からダウンロードすることができます。今後数回の記事にわたって、このアプリケーションのコアとなる機能を段階的に構築していきます。

今回の記事で焦点とするのは、Grails アプリケーションのルック・アンド・フィールの大掛かりな変更です。昨年の連載で扱った Trip Planner のルック・アンド・フィールはフランケンシュタインの如くで、開発者にしか好まれないものでした (それというのも、アプリケーションの美しさよりも、コア機能が興味の対象だったからです)。今回は、CSS による多少の調整といくつかの部分テンプレートを散りばめて、そのままの Grails アプリケーションとはまったく違う外見の Web アプリケーションに仕上げます。この過程のなかで、scaffold 生成、自動タイムスタンプ設定、デフォルト・テンプレートの変更、カスタム TagLib の作成、Bootstrap.groovy や URLMapper.groovy といった重要な構成ファイルの調整など、Grails の機能についても簡単に復習していきます。

この連載について

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

手順を始めるにあたり、まずは Grails 1.1 (この記事を作成している時点ではまだベータ版です) をインストールする必要があります。

Grails 1.1 のインストール

Grails を実行する上では Java 1.5 または 1.6 を使用するのが最適です。コマンド・プロンプトで java -version と入力して、最新の Java バージョンを使用していることを確認してください。

Java 1.5 または 1.6 が使われていることを確認したら、以下のように、いつもながらの単純なステップで Grails をインストールすることができます。

  1. Grails サイトから grails.zip をダウンロードします。
  2. grails.zip を解凍します。
  3. GRAILS_HOME 環境変数を作成します。
  4. PATH に GRAILS_HOME/bin を追加します。

以前の Grails バージョンで作成されたアプリケーションについては、grails upgrade と入力すれば現行バージョンにマイグレーションできますが、Grails の複数のバージョンを使いたい場合にはどうすればよいでしょうか。

UNIX® ライクな OS (UNIX、Linux®、または OS X) を使用している場合、$GRAILS_HOME 環境変数の値をシンボリック・リンクに指定するだけで、簡単に Grails バージョンを切り替えることができます。私が使用しているシステムでは、GRAILS_HOME が /opt/grails を指しています。このように設定されていれば、リスト 1 に記載するような単純な ln -s によってリリース間を切り替えることができます。

リスト 1. UNIX、Linux、または Mac OS X での $GRAILS_HOME のシンボリック・リンクの作成
$ ln -s /opt/grails-1.1-beta1 grails

$ ls -l | grep "grails"
lrwxr-xr-x   1 sdavis  admin        17 Dec  5 11:12 grails -> grails-1.1-beta1/
drwxr-xr-x  14 sdavis  admin       476 Nov 10  2006 grails-0.3.1
drwxr-xr-x  16 sdavis  admin       544 Feb  9  2007 grails-0.4.1
drwxr-xr-x  17 sdavis  admin       578 Apr  6  2007 grails-0.4.2
drwxr-xr-x  17 sdavis  admin       578 Jun 15  2007 grails-0.5
drwxr-xr-x  19 sdavis  admin       646 Jul 30  2007 grails-0.5.6
drwxr-xr-x  18 sdavis  admin       612 Sep 18  2007 grails-0.6
drwxr-xr-x  19 sdavis  admin       646 Feb 19  2008 grails-1.0
drwxr-xr-x  18 sdavis  admin       612 Apr  5  2008 grails-1.0.2
drwxr-xr-x  18 sdavis  admin       612 Oct  9 21:46 grails-1.0.3
drwxr-xr-x  18 sdavis  admin       612 Nov 24 20:43 grails-1.0.4
drwxr-xr-x  18 sdavis  admin       612 Dec  5 11:13 grails-1.1-beta1

Windows® システムを使用している場合に最も確実な方法は、%GRAILS_HOME% 変数を直接変更することです。ただし変更した後は、既存のコマンド・プロンプトを忘れずに再起動してください。

grails -version と入力して、最新のリリースが使用されていること、そして GRAILS_HOME 変数が正しく設定されていることを確認します。このコマンドを実行すると、リスト 2 のような出力が表示されます。

リスト 2. grails -version による出力
$ grails -version
Welcome to Grails 1.1-beta2 - http://grails.org/
Licensed under Apache Standard License 2.0
Grails home is set to: /opt/grails

Grails 1.1 がインストールされたので、これで、新しいアプリケーションの作成に取り掛かれます。


アプリケーションの作成

grails create-app blogito と入力して、初期ディレクトリー構造の scaffold を生成します。新規 blogito ディレクトリーにカレント・ディレクトリーを変更し、grails create-domain-class Entry と入力します。これによって作成されたクラスが、ブログ・エントリーを表すことになります。grails-app/domain で Entry.groovy ファイルを探し、このファイルにリスト 3 のコードを追加します。

リスト 3. Entry クラスの作成
class Entry {
  static constraints = {
    title()
    summary(maxSize:1000)
    dateCreated()
    lastUpdated()
  }
  
  String title
  String summary
  Date dateCreated
  Date lastUpdated
}

Entry のそれぞれに、title フィールドと summary フィールドがあります。maxSize 制約を 1,000 文字に設定すると、動的に scaffold として生成される HTML フォームには、単純なテキスト・フィールドの代わりに summary フィールドのテキスト域が用意されます。

次回の予告: ブログ・エントリーにコンテンツを追加する

次回の記事では、ブログ・エントリーの実際のコンテンツを保持するために body フィールドを追加しますが、とりあえず今は、body フィールドについては無視します。このフィールドを完全に実装するには、Grails がどのようにユーザーを認証してファイルをアップロードするかを理解する必要があるからです。Blogito では、エンド・ユーザーがペイロードとして HTML や画像、さらにはポッドキャスト用の MP3 などの多種多様なデータをアップロードすることができます。

dateCreatedlastUpdated は、Grails では魔法のようなフィールドの名前であることを思い出してください。この 2 つのフィールドを使えば、最新の Entry が常にリストの先頭に配置されるようにできるため、ブログ・アプリケーションには申し分のないタイムスタンプ・フィールドとなります。

ドメイン・クラスが準備できたら、次のステップとしてコントローラーを作成します。まず、grails create-controller Entry と入力します。grails-app/controllers/EntryController.groovy に、リスト 4 のコードを追加してください。

リスト 4. EntryController の作成
class EntryController {
    def scaffold = Entry
}

一見単純に見える def scaffold = Entry の行が、Grails に Entry クラスの残りのサポートの scaffold を生成するように指示します。この後すぐにわかりますが、生成されるエントリー・テーブルには、Entry クラスの各フィールド列に対応する列があります (それに加え、主キーに対応する ID フィールドと、オプティミスティック・ロック用のバージョン・フィールド)。さらに、平凡ながらも重要な CRUD (Create/Retrieve/Update/Delete) 機能すべてを提供する GSP (Groovy Server Page) の一式も生成されます。

grails run-app と入力して、Web ブラウザーで http://localhost:8080/blogito にアクセスしてください。EntryControllerNew Entry の順にクリックします。嬉しいことに、すべての Entry フィールドが作成フォームに表示されるはずです (図 1 を参照)。しかし同時に悪い知らせもあります。それは、ユーザーがこれらのタイムスタンプ・フィールドをあれこれ編集できるようになっていることです。この問題を解決するには、デフォルト・テンプレートを調整する必要があります。

図 1. Create Entry フォームの編集可能なタイムスタンプ・フィールド
Create Entry フォームの編集可能なタイムスタンプ・フィールド

デフォルト・テンプレートの調整

問題の解決策としては、grails generate-views Entry と入力し、GSP ファイルから手動で dateCreated フィールドと lastUpdated フィールドを削除するという方法が考えられますが、それは症状を取り除くだけであって、問題を根本から解決することにはなりません。必要な対策は、この 2 つのフィールドが二度と作成フォームと編集フォームに表示されないようにすることです。そのための最善の方法は def scaffold の背後にあるテンプレートを変更することです。

grails install-templates と入力し、src/templates/scaffolding で create.gsp ファイルと edit.gsp ファイルを探します。この 2 つのファイルのそれぞれで、excludedPropsdateCreatedlastUpdated を追加します (リスト 5 を参照)。

リスト 5. list.gsp および show.gsp テンプレートでのタイムスタンプ・フィールドの除外
excludedProps = ['version',
                 'id',
                 'dateCreated',
                 'lastUpdated',
                 Events.ONLOAD_EVENT,
                 Events.BEFORE_DELETE_EVENT,
                 Events.BEFORE_INSERT_EVENT,
                 Events.BEFORE_UPDATE_EVENT]

Grails を再起動して、タイムスタンプ・フィールドが表示されないことを確認してください (図 2 を参照)。

図 2. タイムスタンプ・フィールドが除外されたフォーム
タイムスタンプ・フィールドが除外されたフォーム

ソート順の変更

新しいエントリーを追加するとすぐに、テーブルが ID 順にソートされます (デフォルト)。ブログのエントリーは、通常、新しい順にソートされて最新のエントリーが先頭にリストされます。Grails の以前のバージョンでデフォルトのソート順を変更するということは、EntryController.groovy ファイルのリスト・クロージャーを手作業で編集することを意味します。既存の max 行の下に 2 つの新しいソート行を追加する作業は、特に面倒というわけではありません (リスト 6 を参照)。問題は、このコードが裏で動的に scaffold として生成されなくなることです (ベースとなるデフォルトの実装を確認するには、src/templates/scaffolding/Controller.groovy を調べるか、grails generate-controller Entry と入力してください)。

リスト 6. Grails 1.0.x でのソート
def list = {
    if(!params.max) params.max = 10
    if(!params.sort) params.sort = "lastUpdated"
    if(!params.order) params.order = "desc"
    [ entryList: Entry.list( params ) ]
}

Grails 1.1 では、単純ながらも非常に便利な機能を静的マッピング・ブロックに追加しています。それが、sort です。リスト 7 のマッピング・ブロックを Entry.groovy ファイルに追加してください。ドメイン・クラスでソートを操作することによって、引き続きコントローラーの def scaffold を実行することができます。

リスト 7. static mapping ブロックへの sort の追加
class Entry {
  static constraints = {
    title()
    summary(maxSize:1000)
    dateCreated()
    lastUpdated()
  }
  
  static mapping = {
    sort "lastUpdated":"desc"
  }  
    
  String title
  String summary
  Date dateCreated
  Date lastUpdated
}

Grails を再起動して、編集後のエントリーが実際にリストの先頭に配置されることを確認してください (図 3 を参照)。

図 3. 新しいソート順の確認
新しいソート順の確認

開発モードでのダミー・レコードの作成

Grails を再起動する度に、エントリーがなくなっていることにお気付きですか。思い出してください。これは 1 つの機能であって、バグではありません。エントリー・テーブルは Grails を起動する度に作成され、シャットダウンする度に破棄されます。これを確かめるには、grails-app/conf/DataSource.groovy を開いてください。開発モードの db-create の値は明らかに、create-drop に設定されているはずです。

この値を update に変更しても構いませんが、この設定は理想的とは言えません。開発プロセスの初期段階では、一般にスキーマはかなり流動的です。通常はフィールドの追加と削除、制約の変更などを繰り返すことになるため、すべてが落ち着くまでは、db-create をそのまま create-drop に設定しておくのが最善だと思います。

開発モードでサンプル・データを何度も入力し直す面倒を省くには、ちょっとしたロジックを grails-app/conf/BootStrap.groovy に追加します。リスト 8 は、Grails が起動する度に新しいレコードを挿入するコードです。

リスト 8. 開発モードでのダミー・レコードの追加
import grails.util.GrailsUtil

class BootStrap {

  def init = { servletContext ->
    switch(GrailsUtil.environment){
      case "development":
        new Entry(
          title:"Grails 1.1 beta is out", summary:"Check out the new features").save()
        new Entry(
          title:"Just Released - Groovy 1.6 beta 2", summary:"It is looking good.").save()
      break

      case "production":
      break
    }

  }
  def destroy = {
  }
}

Grails をもう一度再起動してください。今度は、レコードが入力された状態のエントリー・テーブルが表示されるはずです (図 4 を参照)。

図 4. 起動時に表示されるダミー・レコード
起動時に表示されるダミー・レコード

リストの整形

リスト・ビューに表示されるデフォルトの HTML テーブルは手始めとしては十分なものですが、Blogito の場合に長期的なソリューションにならないのは明らかです。一般に、ブログ・ページの日付、タイトル、要約フィールドは横に並べられるのではなく、エントリーごとに縦に表示されます。

このように変更するには、まず grails generate-views Entry と入力します。以前は動的に scaffold として生成されていた GSP ファイルが grails-app/views/entry にあるはずです。list.gsp をテキスト・エディターで開いて、ヘッダーのタイトルを Entry List から Blogito に変更します。<h1><g:if> のブロックを削除し、既存の <div class="list"> をリスト 9 のコードに置き換えます。

リスト 9. list.gsp ビューの変更
<div class="list">
 <g:each in="${entryInstanceList}" status="i" var="entryInstance">
  <div class="entry">
   <span class="entry-date">${entryInstance.lastUpdated}</span>
   <h2><g:link action="show" id="${entryInstance.id}">${entryInstance.title}</g:link></h2>
   <p>${entryInstance.summary}</p>                
  </div>  
 </g:each>
</div>

コードが大幅に単純になっていることに注目してください。<fieldValue> タグは削除して構いません。このタグは、ドメイン・クラス・フィールドを HTML フォームのフィールドにバインドするのに役立ちますが、ここでは実際の値を追加するわけではないからです。各 Entry はクラスが指定された <div> にラップし、lastUpdated フィールドはクラスが指定された <span> にラップします。クラス属性が提供するのは、この後取り掛かる CSS フォーマット設定のフックです。title フィールドと summary フィールドは、昔ながらの簡素な HTML タグである <h> タグと <p> タグにラップします。

CSS の基本 (1): <div> と <span> との違いについて

プログラマーのなかには、CSS の話や、ソフトウェア・エンジニアリングではなくグラフィック・デザインに関連する技術の話になると、途端に興味を示さなくなる人がいます。CSS が複雑になってくると、とことんまで複雑になり得るのは確かですが、その逆もまた然りで、単純な CSS は、至って単純です。

HTML タグは大まかに、ブロック・タグとインライン・タグという 2 つのカテゴリーに分かれます。<h1><p><div> などのブロック・タグで囲むのは、大まかに分類された大きなコンテンツの塊です。ブラウザーは通常、各ブロック要素の終わりに暗黙的な改行を挿入します。<h1><p> には事前定義されたルック・アンド・フィールがあります。情報のブロックは大抵の場合、<div> で囲むため、このタグにクラスを指定して、カスタム・スタイルをタグに適用することができます。

<a><strong><span> などのインライン要素は、パラグラフ全体ではなく、1 つや 2 つの単語を囲むために使用するのが通常です。インライン要素の終わりには、改行は追加されません。また、<strong><em> などのインライン要素にはブロック要素と同じくデフォルトのフォーマットが関連付けられますが、<span> には CSS によってフォーマットを適用するしかありません。

<span> 要素と <div> 要素にどのようにクラスを指定するかも、初心者にとっては混乱の種です。class 属性は、ページ上の複数の要素で何回でも利用されるように意図されています。entryentry-date などの CSS クラスは、同じクラスを持つすべての要素が同じように表示されるように作成します。これらのクラスはスタイル・シートの中では、例えば .entry.entry-date のように、ドットで始まる形で示されます。

id 属性を持つ要素を見かけることもあります。id は HTML 文書内で一意でなければなりません。この記事では後ほど <div id="header"> を作成しますが、これはつまり、ページごとにヘッダー要素は 1 つしか存在しないことを意味します。id は、スタイル・シートでは例えば #header のように、先頭にシャープが付いた形で示されます。

CSS の基本について簡単に復習するには、「参考文献」を参照してください。

ブラウザーでリスト・ビューを最新の表示にしてください (図 5 を参照)。この時点ではまだ改善されているとは言い難い外観ですが、いくつかの新しい CSS 命令を追加することによって、外観は見違えるほど良くなります。

図 5. CSS を使用していない新しいリスト
CSS を使用していない新しいリスト

リスト 10 の CSS を web-app/css/main.css の末尾に追加します。

リスト 10. CSS による list.gsp ビューのカスタマイズ
/* Blogito customizations */
.entry {
  padding-bottom: 2em;
}

.entry-date {
  color: #999;
}

もう一度 Web ブラウザーを最新の表示にすると、多少見栄えが良くなっているはずです (図 6 を参照)。CSS での作業はこれで終わったわけではありませんが、最初の作業としては良い出来栄えと言えます。

図 6. CSS を使用した新しいリスト
CSS を使用した新しいリスト

Date TagLib の作成

CSS の基本 (2): empx との違いについて

main.css を調べてみると、フォント・サイズの多くはピクセル単位で表現されていることに気付くはずです。固定サイズを使用しても技術的にはまったく問題ありませんが (実際、かなり一般的に使用されています)、ユーザビリティーという点ではマイナスです。視覚に障害を持つユーザーや、とてつもなく大型のモニター (あるいは解像度が極めて高いモニター) を使用する究極のマニアは一様に、設定された固定フォント・サイズについて小声でブツブツ文句を言っています。ウェブマスターのモニター上では適切に見える表示が、シネマ・サイズのスクリーンから iPhone に至るまでの世間一般に出回っている多種多様なディスプレイでも適切に表示されることは稀なことです。

CSS でのピクセルによる測定単位は、必ずしも悪いというわけではありません。例えば、画像などの固定サイズの要素にはピクセルの単位が最適です。しかし一般的には、フォント・サイズには相対的な測定単位 (em など) のほうが適しています。1em は、ブラウザーが設定するデフォルト・フォント・サイズまたはそれを囲む親要素の 100 パーセントに相当し、 2em はデフォルト・フォント・サイズの 2 倍に相当するといった具合です。

詳細は、「参考文献」を参照してください。

ここで、lastUpdated の日付がもっとユーザー・フレンドリーに表示されるように手を加えます。再利用可能なコードのスニペットを配置するのに最適な場所は、カスタム TagLib です。grails create-tag-lib Date と入力して、リスト 11 のコードを grails-app/taglib/DateTagLib.groovy ファイルに追加してください。

リスト 11. DateTagLib のコード
import java.text.SimpleDateFormat

class DateTagLib {
  def longDate = {attrs, body ->
    //parse the incoming date
    def b = attrs.body ?: body()
    def d = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").parse(b)
        
    //if no format attribute is supplied, use this
    def pattern = attrs["format"] ?: "EEEE, MMM d, yyyy"
    out << new SimpleDateFormat(pattern).format(d)
  }
}

今度は grails-app/views/entry/list.gsp ファイルで、lastUpdated フィールドを新しく作成した <g:longDate> タグにラップします (リスト 12 を参照)。

リスト 12. list.gsp での <g:longDate> タグの使用
<div class="entry">
  <span class="entry-date"><g:longDate>${entryInstance.lastUpdated}</g:longDate></span>
  <h2>${entryInstance.title}</h2>                  
  <p>${entryInstance.summary}</p>                
</div>

Grails を再起動して Web ブラウザーを最新の表示にすると、図 7 に示すフォーマット設定しなおされた日付が表示されます。

図 7. カスタム <g:longDate> タグを使用して新しくフォーマット設定された日付
カスタム <g:longDate> タグを使用して新しくフォーマット設定された日付

部分テンプレートの作成

レイアウトの見栄えはかなり上出来です。そこで、このレイアウトを show.gsp にも使用することにします。grails-app/views/entry に _entry.gsp ファイルを作成して、リスト 13 のコードを追加してください (もちろん、list.gsp のコードをカット・アンド・ペーストするだけでも構いません)。

リスト 13. _entry.gsp のコード
<div class="entry">
 <span class="entry-date"><g:longDate>${entryInstance.lastUpdated}</g:longDate></span>
 <h2><g:link action="show" id="${entryInstance.id}">${entryInstance.title}</g:link></h2>
 <p>${entryInstance.summary}</p>
</div>

新しく作成した部分テンプレートを使用するには、list.gsp をリスト 14 のように調整します。

リスト 14. list.gsp での _entry.gsp 部分テンプレートの使用
<div class="list">
  <g:each in="${entryInstanceList}" status="i" var="entryInstance">
    <g:render template="entry" bean="${entryInstance}" var="entryInstance" />
  </g:each>
</div>

これで、部分テンプレートを show.gsp でも使用することができます (リスト 15 を参照)。

リスト 15. show.gsp での _entry.gsp 部分テンプレートの使用
<div class="body">
  <g:render template="entry" bean="${entryInstance}" var="entryInstance" />
  <div class="buttons">
    <!-- snip -->
  </div>
</div>

ブラウザーでリスト・ビューを最新の表示にすると、前とまったく同じように表示されるはずです。任意のエントリーのタイトルをクリックして、表示ビューでも日付のフォーマット設定が機能することを確認してください。


ヘッダーのカスタマイズ

全体的に、いい感じにまとまってきました。ここで、Grails のブランドを独自のブランドに置き換えます。

list.gsp または show.gsp で Grails ロゴが参照されている箇所は見当たりません。これは、Grails は SiteMesh を使用して、各種パーツを 1 つのページに組み立てるためです。grails-app/views/layouts/main.gsp を調べると、grails_logo.jpg ファイルがどこで組み込まれているかがわかります。

grails-app/views/layouts に、_header.gsp という名前の別の部分テンプレートを作成して、リスト 16 のコードを追加します。Blogito はメイン・ページに戻るハイパーリングであることに注意してください。

リスト 16. _header.gsp 部分テンプレートのコード
<div id="header">
  <p><g:link class="header-main" controller="entry">Blogito</g:link></p>
  <p class="header-sub">A tiny little blog</p>
</div>

次に、リスト 17 に示すように main.gsp を編集して _header.gsp ファイルをインクルードします。

リスト 17. main.gsp での新しい _header.gsp 部分テンプレートの使用
<body>
  <div id="spinner" class="spinner" style="display:none;">
    <img src="${createLinkTo(dir:'images',file:'spinner.gif')}" alt="Spinner" />
  </div> 
  <g:render template="/layouts/header"/>        
  <g:layoutBody />  
</body>

CSS の基本 (3): paddingmargin との違いについて

ブロック要素の周りに多少のスペースをもたせるために使用する CSS ボックス・モデルは、最初は理解しにくいかもしれません。一言で言うと、padding はブロック内側のスペースを増やす一方、margin はブロック外側のスペースを増やします。

リスト 18 のヘッダーでは、テキストと青いボックスの縁との間にスペースを追加するために padding を使用し、青いボックス外側の header <div>nav <div> との間にスペースを追加するために margin を使用しています。

ブロック要素の 4 辺すべてに一定のスペースを設定するには、padding: 2em; または margin: 2em; を使用します。一方、ブロック要素の特定の一辺にスペースを設定するには、margin-topmargin-rightmargin-bottom、または margin-left を使用して、その一辺を直接参照します。リスト 18 のように、辺ごとに異なる padding を 1 行で設定する場合には、正しい順序を覚えられるようにニーモニック TRBL (Top、Right、Bottom、Left) を使用してください。そうすれば、TRBL (苦労: TRouBLe) なく辺の順序を覚えられるはずです。

CSS ボックス・モデルについての詳細は、「参考文献」を参照してください。

最後の仕上げとして、リスト 18 のコードを web-app/css/main.css に追加します。

リスト 18. _header.gsp 部分テンプレートの CSS フォーマット
#header {
  background: #67c;
  padding: 2em 1em 2em 1em;
  margin-bottom: 1em;
}

a.header-main:link, a.header-main:visited {
  color: #fff;
  font-size: 3em;
  font-weight: bold;
}

.header-sub {
  color: #fff;
  font-size: 1.25em;
  font-style: italic;
}

ブラウザーを最新の表示にして変更を確認してください (図 8 を参照)。任意のエントリーのタイトルをクリックした後、ヘッダーの Blogito をクリックするとメイン・ページが再表示されます。

図 8. 新しいヘッダーのお披露目
新しいヘッダーのお披露目

ログインしている場合にのみナビゲーション・バーを表示させる方法

これが Grails アプリケーションであることを示すもう 1 つの目印にも対処する必要があります。この目印とは、ナビゲーション・バーのことです。認証は次回の記事まで実装しませんが、認証されれいないユーザーに対して今の段階でナビゲーション・バーを非表示にするには、単純な <g:if> テストに <div> をラップします。このテストでは、セッション・スコープに保管された user 変数を調べます。

list.gsp と show.gsp の両方をリスト 19 のように変更してください。

リスト 19. ログインしている場合にのみナビゲーション・バーを表示させる方法
<g:if test="${session.user}">
  <div class="nav">
      <span class="menuButton">
         <a class="home" href="${createLinkTo(dir:'')}">Home</a>
      </span>
      <span class="menuButton">
         <g:link class="create" action="create">New Entry</g:link>
      </span>
  </div>
</g:if>

show.gsp では、同じテストでボタンの <div> を囲みます (最も避けなければならないのは、認証されていないユーザーがブログ・エントリーを編集したり、削除したりすることだからです)。

list.gsp に対しては、もう 1 つ見栄えを良くするための調整を加えます。そのために、paginateButtons <div>body <div> の外側に移動します (リスト 20 を参照)。こうすることによって、バーが画面の端から端まで伸びるため、画面の下部に見栄えの良い視覚的アンカーが追加されることになります。

リスト 20. 見栄えを良くするために body <div> の外側に移動した paginateButtons <div>
<html>
 <head>
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
  <meta name="layout" content="main" />
  <title>Blogito</title>
 </head>
 <body>
  <g:if test="${session.user}">
   <div class="nav">
    <span class="menuButton">
      <a class="home" href="${createLinkTo(dir:'')}">Home</a>
    </span>
    <span class="menuButton">
      <g:link class="create" action="create">New Entry</g:link>
    </span>
   </div>
  </g:if>
   <div class="body">
    <div class="list">
     <g:each in="${entryInstanceList}" status="i" var="entryInstance">
      <g:render template="entry" bean="${entryInstance}" var="entryInstance" />
     </g:each>
    </div>
   </div>    
   <div class="paginateButtons">
    <g:paginate total="${Entry.count()}" />
   </div>
 </body>
</html>

paginateButtons <div>body <div> の隣ではなく、その下に確実に表示されるようにするため、さらにリスト 21 の CSS を追加します。

リスト 21. paginateButtons <div> が画面下部に確実に表示されるようにするための CSS
.paginateButtons{
  clear: left;
}

最後にもう 1 度、ブラウザーを最新の表示にしてください。画面は図 9 のようになっているはずです。

図 9. 非表示にされたナビゲーション・バー
非表示にされたナビゲーション・バー

ホーム・ページの設定

これですべて準備万端に整ったので、EntryController をデフォルト・ホーム・ページに設定します。それには、/ (URL http://localhost:9090/blogito/ の末尾のスラッシュ) を EntryController にリダイレクトするマッピングを追加します。grails-app/conf/UrlMappings.groovy をリスト 22 と同じになるように編集してください。

リスト 22. EntryController をデフォルト・ホーム・ページに設定する方法
class UrlMappings {
    static mappings = {
      "/$controller/$action?/$id?"{
            constraints {
                   // apply constraints here
              }
        }
        "/"(controller:"entry")
        "500"(view:'/error')
   }
}

まとめ

今回の記事で目的としたのは、Grails アプリケーションの見栄えを良くする方法を紹介することです。数行の CSS を追加することで、色、フォント、ブロック要素周囲のスペースなどを変更することができます。また、部分テンプレートと TagLib によって、再利用可能なコード・スニペットを作成することもできます。その結果として出来上がるのは、Grails フレームワークのすべての利点が生かされた、独特なルック・アンド・フィールを持つアプリケーションです。

次回の記事でも引き続き Blogito アプリケーションに肉付けするため、User ドメイン・クラスを追加して複数のユーザーがブログ・エントリーを追加できるようにします。さらに、Grails のコーデックの詳細を探り、カスタム URL マッピングも操作します。完成版のアプリケーションは、http://blogito.org からダウンロードできることをお忘れなく。それでは、次回の記事まで Grails を楽しみながらマスターしてください。

参考文献

学ぶために

  • 連載「Grails をマスターする」: この連載の他の記事を読んで、Grails とこのフレームワークを使って実現可能なすべての内容をよく理解してください。
  • Grails: Grails の Web サイトにアクセスしてください。
  • Grails Framework Reference Documentation: Grails のバイブルとなります。
  • Design Web pages with class」(Molly Holzschlag 著、developerWorks、1999年9月): スタイル・シートのクラスを使用することで、HTML 文書を素早く設計 (または再設計) する 2 通りの方法を調べてください。
  • Care With Font Size: W3C Quality Assurance シリーズで紹介しているフォント・サイズについてのヒントを読んでください。
  • Box Model: CSS での paddingmargin について詳しく学んでください。
  • Groovy Recipes』(Scott Davis 著、Pragmatic Programmers、2007年): Scott Davis の最新の著作で Groovy と Grails の詳細を学んでください。
  • 連載「実用的な Groovy」: developerWorks のこの連載記事では、実用的な Groovy の使用方法を探り、それぞれの方法をいつ、どんな場合に適用するかを解説しています。
  • Groovy: Groovy の Web サイトで、このプロジェクトの詳細を学んでください。
  • AboutGroovy.com: Groovy に関する最新のニュースと記事へのリンクが記載されています。
  • technology bookstore: この記事で紹介した技術やその他の技術に関する本を参照してください。
  • developerWorks Java technology ゾーン: Java プログラミングのあらゆる側面を網羅した記事が豊富に用意されています。

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

  • Grails: 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, Open source
ArticleID=370304
ArticleTitle=Grails をマスターする: Grails アプリケーションの見栄えを良くする
publish-date=01202009