Grailsアップデート状況
本書「はじめてのGrails(工学社刊)」作成時、Grailsの「安定版」はGrails-1.1.1でした。その後、アップデートにともない、本書の記載事項が通用しなくなった箇所も出てきましたので、ここに御紹介します。
3-8節の実行例3-9(49ページ)は、はじめてGrailsアプリケーションを完成させるコマンドです。
2011年9月時点の安定板「grails-1.3.7」におきまして、本書記載の通り
grails generate-all Testdata
と実行しますと、
Domain class not found in grails-app/domain, trying hibernate mapped classes...
などのエラーメッセージが出て、作成に失敗します。
この対策は、以下のようになります。
3-5節(41ページ)において、このアプリケーションを「testapp」という名前にしましたね。(実行例3-2)
そこで、実行例3-9におきましては、この「アプリケーション名(ドメイン名)」とつけて、以下のようにします。
grails generate-all testapp.Testdata
Javaの実行について詳しい人は、「アプリケーション名とかドメイン名とか言っているものは、つまりパッケージ名なんだな」とわかるでしょう。
世の中のアプリケーション名やドメイン名が全てパッケージ名というわけではありませんが、Grailsの場合は、そうです。これは、このあと示すように、各プログラムの内容にもときどき関わってきます。本書の通りに書いていて、どうもエラーが出る場合、「パッケージ名をなにかするんだな」と疑ってみてください。
ほかのアプリケーションの場合も、同様にドメイン名(アプリケーション名)をつけて実行してみてください。
なお、コマンドを打つ場所は、今までと同じです。
以下に具体的な実行例を挙げますが、「もうわかった」という方は読み飛ばして次に進んでいただいてよいと思います。
4-3節の実行例4-7(67ページ)
及び7-3節の実行例7-4(187ページ)
grails generate-all glossary.Word
7-2節の実行例7-1(183ページ)
grails generate-all glossary.Categ
8-3節の実行例8-3(205ページ)
及び第8-7節の実行例8-6(214ページ)
grails generate-all testapp.Cage
8-3節の実行例8-4(205ページ)
grails generate-all testapp.Bird
この点、Webで検索すると、やはり多くの悩めるユーザが掲示板などに質問しています。エラーメッセージ中になにか説明をつけるか、確認の質問をしてくれるか、Grails側でも改善してほしいものですね。
アプリケーションの作成に「ドメイン名」が関わるようになったため、自動作成されるファイルの構造も変わりました。
3-7節 47ページ の最終行に以下のように書いてありますね。
「grails-app」フォルダの中に「domain」フォルダがあり、これを開いてみると「Testdata.groovy」というファイルがあります
この「domain」フォルダの中に、さらに「testapp」フォルダが作成され、そこに「Testdata.groovy」が置かれます。
このように、「grails-app」フォルダ中の、「domain」及び「controllers」フォルダの中には、さらにアプリケーション名のフォルダが入って、アプリケーションファイルが置かれるようになりました。
ただし、「views」フォルダの構造だけは変わりません。
以下に具体例を挙げますが、「もうわかった」という方は読み飛ばして次に進んでいただいてよいと思います。
4-2節 64ページの中央付近
「glossary」フォルダの「grails-app/domain」というフォルダを開いてみましょう。「Word.groovy」というファイルができています
ここは、「grails-app/domain/glossary」フォルダです。
4-3節 67ページの最終行付近
「controllers」フォルダを開くと、そこに「WordController.groovy」というファイルができています
ここは、「controllers/glossary」フォルダです。
一方、4-3節 68ページの中央付近
次に、「views」フォルダです。こんどは、「word.groovy」という名前のフォルダがあります。
これは不変です。
アプリケーション「testapp」についても同様です。4-3節の69ページ、上のほうに、まとめて書いてあります。
「testapp」アプリケーションの「controllers」フォルダには、「TestdataController.groovy」ファイルがあります。
ここは「controller」フォルダの中にさらに「testapp」フォルダがあって、その中にファイルが置かれます。
「views」フォルダには、まず「testdata」フォルダがあって、そこに「gsp」ファイルがあります。
これは不変です。
「アプリケーション名」が「パッケージ名」
前述のように、Grailsではバージョン1.3あたりから、アプリケーション名がプログラムの作り方に関わるようになりました。
これは、Javaの「パッケージ」というプログラムの分類法に相当します。
「Word」「Categ」などはJavaの「クラス」に相当し、アプリケーション名「glossary」が「パッケージ」に相当します。
「Word」や「Categ」はパッケージ名を含めて「glossary.Word」「glossary.Categ」と呼ぶのが正式の呼び方になったのです。
そのため、パッケージ名を含めてクラスを書くように変更になっている場所があります。自動記入される内容においては、それらは一連の「GSPファイル」です。
実は、自動記入されたファイルの内容が本書と違っている点は、
後述のようにパッケージ名に関係ないもののほうが多いのです。
自動記入される内容の変更点
自動作成される各「GSPファイル」では、ファイルの先頭に、以下のような記述がなされます。
アプリケーション「testapp」における、小アプリケーション「Testdata」の、各GSPファイル
<%@ page import="testapp.TestData" %>
アプリケーション「glossary」における、小アプリケーション「Word」の、各GSPファイル
<%@ page import="glossary.Word" %>
これは、Javaのソースの決まりに由来するものです。そこで、Javaの決まりと同じく「インポート文」と呼んでよいと思います。
実は、Javaで使っているWebページ記述形式「JSP」に近い書き方です。
なお、これらの変更に関連して、我々が何か「しなければならない」ということはありません。
また、「ドメイン・クラス」及び「コントローラ」のファイルには、これに相当する変更はありません。
以下に具体例を挙げますが、「もうわかった」という方は読み飛ばして次に進んでいただいてよいと思います。
アプリケーション「glossary」における、小アプリケーション「Categ」の、各GSPファイル
<%@ page import="glossary.Categ" %>
アプリケーション「testapp」における、小アプリケーション「Bird」の、各GSPファイル
<%@ page import="testapp.TestData" %>
アプリケーション「testapp」における、小アプリケーション「Cage」の、各GSPファイル
<%@ page import="glossary.Word" %>
「BootStrap.groovy」に「Cage」「Bird」を書き込むとエラーになる
8-5節及び8-8節で、「BootStrap.groovy」に編集を加えます。このとき、本書の記載の通りに行いますと、Grails1.3以降では、エラーになります。
理由は、やはり「パッケージ名」です。「BootStrap.groovy」に「Cage」や「Bird」のことを書き込むのが原因です。
これらを、それぞれ「testapp.Cage」「testapp.Bird」と書くことによって、解決します。でも、もっと便利な方法は、今GSPファイルに「自動記入されるようになった」のを確認したばかりの「インポート文」を書くことです。
一括インポート文
「BootStrap.groovy」は「コントローラファイル」と同じく、Groovyを用いて書きます。そのため、GSPファイルとは書き方が異なり、むしろJavaに近い書き方をします。
インポート文は以下のような一括インポート文を「BootStrap.groovy」に書いておけば、あとは本書の書き方をそのまま使って大丈夫です。
import testapp.*
なお、「Groovy」の書き方に従い,セミコロンは必要ありません。
念のため、この記載は以下のように、クラスの宣言よりも前、本当にファイルの最初に書きますので、はじめてこのような文を書く場合は、御注意ください。
import testapp.*
class BootStrap{
............
説明のはじめに- 第6章は(かなり)必要なくなります-
Grailsでは、自動作成される「コントローラー」ファイル及び「GSP」ファイルによるWebページの日本語表示は、プロパティファイル「messages_ja.properties」で一括して行います。プロパティファイルは、「grails-app」フォルダの下「i18n」フォルダにあります。
まず、プロパティファイルについての詳細は、第5章124ページをお読みください。
その上で書いたのが、第6章です。第5章で設定された以外の場所も日本語化するには、「Contoller」ファイル及び「GSP」ファイル側のほうに、随所でプロパティファイルを参照するように指定する記述を書かなければなりません。でも、本書で扱ったGrailsのバージョン「1.2M2」では、自動作成にまかせていてはそのような記述が不十分だったので、自分で書き直しました。それが、第6章の主たる部分なのです。
それが正式版1.2.0以降では「改良」され、「Contoller」ファイル及び「GSP」ファイルの内容が強化されたので、これらを自分で書き直さなくても、プロパティファイルに追記するだけで、十分日本語化が可能になりました。つまり、
「Contoller」ファイル及び「GSP」ファイルを何度作り直しても、「日本語化」に関しては、書き直す必要がなくなります。
本書で言いますと、第7章187ページあたりで「今まで編集したviews/wordフォルダのGSPファイルが上書きされてしまいます」と嘆いている部分が、嘆く必要がなくなるのです。
そのかわり、第5章で各ファイルを解読する内容がややこしくなります。ですから、ここで説明しましょう。第5章の進行に沿って、各ファイルごとに説明していきます。特に、Contollerファイルには日本語化と関係ない変更も、小さいですがありますので御注意ください。
ただし、第6章の中にあるプロパティファイルの「書き方」は随所で使います。また、最後の6-5節「Grailsアプリケーションの実行に関する注意事項」は大事ですから、日本語化作業が(かなり)必要なくなってもゼヒお読みください。
WordController.groovyを例に見る「コントローラー」ファイルの変更点
各アクションの記述順序が変更
本書では各アクションをindex, list, show, delete, edit, update, create, saveの順に説明していますが、1.2.0版以降での各アクションの記述順序は以下のようになっています。
index, list, create, save, show, edit, update, delete
でも、本をめくり直すよりは画面をスクロールするほうが速いと思われますので、これからの説明では、本書の記述順序で説明します。恐縮ですが、新しいバージョンの「WordController」ファイルのほうで該当アクション名を探して、比べてください。
アクション「list」における変更(5-6節 90ページから)
アクション「index」の変更はなく、「list」からの変更になります。実はこれは、日本語化とは関係ないのですが、小さい変更ですし、また改めてご覧いただくのも不便でしょうからここに記します。
リスト5-6に抜き出して書かれている部分です。
変更前:
params.max ? params.max.toInteger() : 10
変更後:
params.max ? params.int('max') : 10
最終的な結果は全く変わりありません。「maxというパラメータ名で送られてきた値は文字列なので、整数に変換する」ということです。でも、変更後の書き方は「安全な書き方」なのだそうです(Grails1.2リリースノートによる。古いリリースノートなので、将来リンク切れになった際はご容赦ください)。送られて来た値がまかりまちがって整数に変換できないような場合にも、「空の値をそのまま出したり例外エラーを出したりしない措置」とあります。でも、どんな措置がとられるのかは説明がないのでわかりません。
アクション「show」における変更(5-7節 96ページから)
ここからが、「日本語化」を楽にする変更です。
以後のコードでは、
茶色の背景色のコードは「そういう風に変更されているのを確認する」
だけです。一方、
紫色の背景色のコードは、実際にプロパティファイルに追記
してみてください。コードがどのようにWebページに反映されるのか確認できます。プロパティファイルは、「grails-app」フォルダの下「i18n」フォルダにある「messages_ja.properties」です。
では最初に、99ページのリスト5-15以降、「1行目には何が書いてあるのでしょうか」のところです。この変更、しかし逆を言えば「日本語化」という目的以外には何も変わっていません。
変更前:
flash.message = "Word not found with id ${params.id}"
変更後:
flash.message =
"${message(
code: 'default.not.found.message',
args: [
message(code: 'word.label', default: 'Word'),
params.id
]
)
}"
上記変更後の記述は、見やすいように改行して表示しています。
変更後の書き方は、本書のGrailsのバージョンにおいては「6-4節「flashメッセージを日本語化」(172ページ)で手作業でする必要があった」ことが、すでに自動でなされているのです。
しかし、いきなり第6章の内容を読むというのも大変です。そこで、ここでざっと説明しますので、それを手がかりに、詳細は172ページ以降をお読みください。
まず、flash.messageの中身は、"$message(....)"という文字列です。「$」がついているのは、「コードを実行して得られる文字列」という意味です。ここでは、「messageメソッドで得られる文字列」です。
messageメソッドをどのように行うかが(...)の中に書いてあります。「code」と「args」という二つの項目が指定されています。
「code」は、プロパティファイルの中に、以下のように書きます。プロパティファイルは、「grails-app」フォルダの下「i18n」フォルダにある「messages_ja.properties」です。
default.not.found.message=ID{1}の{0}は見つかりません
{1}と{0}の部分には、「args」で指定した内容が入ります。
「args」には二つの要素があります。0番目の要素が{0},1番目の要素が{1}に入るのですが、英語と日本語では語順を逆にしたほうが表現として自然なので、「args」で用意してくれた要素の順番と逆の使い方になっています。
1番目のほうがわかりやすいですね。「params.id」は、99ページで説明の通り、パラメータに指定したidです。
0番目のほうは、これまたプロパティファイルに指定します。以下のように書きます(本書では5-15節 125ページで行っている作業です)
これで、以後「code:'word.label'」と書かれたところは全て「用語」と表示されることになります。
そして、最終的に、メッセージの内容は、指定したパラメータが23だった場合は「ID23の用語は見つかりません」になります。
アクション「delete」における変更(本書101ページから)
「日本語化」を楽にするための、新しい変更が2箇所あります。他はアクション「Show」における変更と同じです。
まず、5-8節 103ページのリスト5-21の2行目、「flash.message」の指定です。ファイルの削除が完了したときのメッセージです。
変更前:
flash.message = "Word ${params.id} deleted"
変更後:
flash.message = "${message(code: 'default.deleted.message',
args: [message(code: 'word.label', default: 'Word'),
params.id])}"
「Show」アクションでリスト5-15を変更した内容とほとんど同じしくみですから、改行も少しサボりました。
要は「default.deleted.message」の内容が「ID7の用語を削除しました」というようなメッセージになるように、{0}と{1}を使ってプロパティファイルに書けばよいのです。
default.deleted.message=ID{1}の{0}を削除しました
もうひとつは、104ページのリスト5-23の2行目、ファイルの削除に失敗したときのメッセージです。
変更前:
flash.message = "Word ${params.id} could not be deleted"
変更後:
flash.message = "${message(code: 'default.not.deleted.message',
args: [message(code: 'word.label', default: 'Word'),
params.id])}"
default.not.deleted.messageの内容をプロパティファイルに書きます。たとえば「ID7の用語は削除できませんでした」というようなメッセージは、{0}と{1}を使って以下のようになります。。
default.not.deleted.message=ID{1}の{0}は削除できませんでした
アクション「edit」における変更(5-9節 105ページから)
アクション「Show」における変更と同じです。
アクション「update」における変更(5-10節 106ページから)
いずれも日本語化のための変更ですが、ひとつ目の109ページ、リスト5-29の変更はちょっとめんどくさいです。
変更前:
wordInstance.errors.rejectValue("version",
"word.optimistic.locking.failure",
"Another user has updated this Word while you were editing.")
リスト5-29は、他の誰かが先にこのデータを編集してしまったときに、「このデータはすでに他のユーザによって変更されています」というメッセージを出すための記述です。
実は、本書自体にひとつ訂正があります。変更前のリスト5-29の太字の部分です。本書ではここを「Grailsの都合ですから気にしません」と書いてしまったのですが、実はこれも「プロパティファイル」に指定すれば日本語化できる「コード」です。指定しなければ"Anoter user has..."というメッセージになります。油断しました。すみません。
それをふまえて、変更後のコードを見てみましょう。
変更後:
wordInstance.errors.rejectValue("version",
"default.optimistic.locking.failure",
[message(code: 'word.label', default: 'Word')] as Object[],
"Another user has updated this Word while you were editing")
めんどくさそうですが、ガンバって読みましょう。まず、プロパティファイル名に指定する「コード名」がword.optimistic.locking.failureからdefault.optimistic.locking.failureに変わっています。これは単なるコード名の変更ですから、変更後はプロパティファイルに
default.optimistic.locking.failure=このデータはすでに他のユーザによって変更されていますというようなメッセージ
と書けばよいだけです。今、まだ内容が確定していないので、日本語部分はいいかげんな仮の記述にしています。これから確定していきます。
さて、「このデータ」を「この用語」にするために使うのが、[message(code: 'word.label', default: 'Word')]です。
「word.label」は実は、5-15節の125ページ、リスト5-53によってプロパティファイルに登録してあります。確認してください。「用語」という日本語に対応させてあります。
[] で囲まれているのは、これが「配列」だからです。配列であるというのはこれぞまさにGrailsの都合で、今の場合は要素が1つしかありません。そこで、この要素を{0}として、「この用語はすでに他のユーザによって変更されています」という日本語になるように、プロパティファイルに以下の記入をします。
default.optimistic.locking.failure=
この{0}の値はすでに他のユーザによって更新されています
as Object[]もGrailsの都合です。[]の配列には文字列がくるか数値がくるかわからないので、エラーにならないように「オブジェクトなら何でも受け付ける」ように指定しているのです。
と、いうことで、それほどタイヘンな変更ではなかったのでした。
「update」アクションのもうひとつの新しい変更は、111ページのリスト5-33です。今のに比べれば、たいしたことはありませんね。
変更前:
flash.message = "Word ${params.id} updated"
変更後:
flash.message =
"${message(code: 'default.updated.message',
args: [message(code: 'word.label', default: 'Word'),
wordInstance.id])}"
プロパティファイルへの追記は、上記の太字の部分に相当する日本語です。
default.updated.message=ID{1}の{0}を更新しました
{0}がwordInstance.idでこのデータのID, {1}が'word.label'で表わされる日本語「用語」です。
アクション「save」における変更(5-12節 114ページから)
アクション「create」には変更事項はありませんので、アクション「save」に移ります。
115ページのリスト5-42です。これも、今まで行って来たのと同様です。
変更前:
flash.message = "Word ${wordInstance.id} created"
変更後:
flash.message =
"${message(code: 'default.created.message',
args: [message(code: 'word.label', default: 'Word'),
wordInstance.id])}"
プロパティファイルへの追記は、上記の太字の部分に相当する日本語です。
default.created.message=新しい{0}をID{1}で作成しました
{0}がwordInstance.idでこのデータのID, {1}が'word.label'で表わされる日本語「用語」です。
以上、「コントローラー」ファイルに自動記入される内容において、主に「message」メソッドの多用による変更事項を確認しました。
「views/word」内の各ファイルの例に見る、GSPファイルの変更点
「views/word」などに入っている表示用のGSPファイルも、ワタシたちはプロパティファイルにのみ追記すればよくなりました。
そこで、第5章の「どこが」「どう変更されたので」第6章の作業が必要なくなったのか、そしてプロパティファイルには「何を」追記すればいいのか、見ていきましょう。
list.gspにおける変更(119ページから)
まず、5-15節 126ページのリスト5-54です。
変更前:
<title>${entityName} List</title>
本書で暑かったGSPファイルでは、このListという単語が直接list.gspに書かれていたため、Webページには「用語List」のような表示がされていました。そこで、直接list.gspを書き換えていました。6-2節の165ページあたりの内容です。
変更後は、要するにその変更を、すでにやってくれているのです。と、言っても本書の方法よりカッコイイ方法です。
変更後:
<title><g:message code="default.list.label" args="[entityName]" /></title>
<g:message>は、GSPファイル上でmessageメソッドを呼んだのと同じことです。同様codeとargsでメッセージの内容を指定しますが、「Grailsタグ」である<g:message>の中では、変数entityNameに「${...}」を使用する必要がないということに注意が必要です。[...]は、「配列だけどここはGrailsの都合で要素1個だけ」でしたね。
と、言っても、ワタシたちの作業は、プロパティファイルに「用語の一覧」という表示が得られるように「default.list.label」の指定をするだけです。
変数entityNameは、6-2節 164ページで説明した通り、「用語」という日本語に置き換え可能になっていますから、これを使います。
default.list.label={0}の一覧
{0}にentityNameの内容、すなわち「用語」が入ることになります。
同様、「New」という英語も、list.gspに直接書くのではなく、プロパティファイルで日本語化可能になります。
変更前:
New ${entityName}
変更後:
<g:message code="default.new.label" args="[entityName]" />
これに対応するプロパティファイルへの追記:
さてここで、記載箇所が前後して申し訳ないのですが、他に修正箇所もありますので、127ページ リスト5-56 を見てください。これは、「ホーム」に戻るメニュー・ボタンの書き方です。
変更前:
<span class="menuButton" >
<a class="home" href="${resource(dir:' '}}">
Home
</a>
</span>
これが、新しいバージョンでは2カ所変更されています。
<span class="menuButton">
<a class="home" href="${createLink(uri: '/')}">
<g:message code="default.home.label"/>
</a%gt;
</span>
ひとつは、「ホーム」のURLの表し方です。変更前は
resource(dir:'')
変更後は
createLink(url:'/')
これは、Grailsの「方針変更」によるものです。本書の時点では、「ホーム」は「サブフォルダのない状態」という「フォルダとファイル」の関係で表わしていましたが、変更後は「URLアドレス」で表わす方針になり、「ドキュメントルート」を指すことになったのです。コンピュータ上のどこにあるかを考えるのはやめよう、という「クラウド」的な思想ですね。
「日本語化」に関わる変更はもうひとつのほうで、先ほど確認した<:g:message>タグを用い、「Home」を日本語化できるようになっています。
プロパティファイルに「default.home.label」の日本語の値を書けばよいのですが、まあHomeはHomeでいいような気もしますね。
なぜこの部分にだけ「default:'Home'」の記載がないのかはわかりません。もっと深層で決められているのかも知れません。
show.gspにおける変更(5-16節 139ページから)
まず、147ページのリスト5-82です。
変更前:
<g:actionSubmit class="edit" value="Edit" />
リスト5-82 の <g:actionSubmit> タグでは、valueの値がactionの値と同じであるということを前提に、actionの値を省略してあります。
これが、以下のように変更されています。変更後はvalueの値を日本語化できるようになっているので、actionの値も指定されています。
変更後:
<g:actionSubmit class="edit" action="edit" value="${message(code: 'default.button.edit.label', default: 'Edit')}" />
プロパティファイルへの追記:
default.button.edit.label=編集
本書では、6-3節 168ページのリスト6-10及びリスト6-12で、結果的には同じとなる変更をしています。
どこが違うかといいますと、まず、プロパティファイルに追記するときの名前です。本書での「view.edit」が、変更後の「default.button.edit.label」
に相当しているのです。
そして、本書では、リスト6-12を長い文にする代わりに、
$message(code: 'view.edit', default: 'Edit')}を「buttonEdit」という変数で表わすことにするからネ
ということを、show.gspの<head>タグの間に書いておいたのです。それがリスト6-10です。実は、<g:set>:タグの使い方を練習したかったというのがホントの理由です。
「show.gsp」のもうひとつの変更点は、148ページ リスト5-83です。
これも、6-13節 168ページ リスト6-13以降で本書が行っている「JavaScriptのコードの文字列を日本語化する方法」をほぼ、Grails側でやってくれたことに相当します。
変更前:
<g:actionSubmit class="delete"
onclick="return confirm('Are you sure?');" value="Delete" />
変更後:
<g:actionSubmit class="delete" action="delete"
value="${message(code: 'default.button.delete.label', default: 'Delete')}"
onclick="return confirm(
'${message(code: 'default.button.delete.confirm.message',
default: 'Are you sure?')}');"/>
「onclick属性」のめんどくさい書き方は、本書でも168ページ以降で紹介しておりますが、基本は以下の通りです。
onclick="return confirm(ナニナニ);"
上の「ナニナニ」の部分が、以下の通りです。
二重引用符の中に、さらに引用符が必要なので、単一引用符を用いることで競合を防いでいます。
上の「ウニウニ」の部分が、以下の通りです。
code: 'default.button.delete.confirm.message', default: 'Are you sure?'
変更後は、プロパティファイルに二つのコードを追記します。
default.button.delete.label=削除
default.button.delete.confirm.message=よろしいですか?
他のGSPファイルとプロパティファイルにおける変更のまとめ
では、残る「edit.gsp」及び「create.gsp」ファイルで「バージョンアップにより変更された箇所」と、それにともなう「ワレワレがプロパティファイルに追記すべき項目」を一気にまとめましょう。
プロパティファイル:
「コントローラ」ファイルの内容も含めて、結局これだけの追記をします。
default.not.found.message=ID{1}の{0}は見つかりません
default.updated.message=ID{1}の{0}を更新しました
default.created.message=新しい{0}をID{1}で作成しました
default.deleted.message=ID{1}の{0}を削除しました
default.not.deleted.message=ID{1}の{0}は削除できませんでした
default.create.label={0}の新規作成
default.list.label={0}の一覧
default.button.create.label=作成
default.edit.label={0}を編集
default.new.label=新規の{0}
default.button.update.label=更新
default.button.delete.label=削除
default.button.delete.confirm.message=よろしいですか?
default.show.label={0}を表示
default.button.edit.label=編集
word.id.label=ID
word.en.label=英語
word.ja.label=日本語
word.label=用語
以下、プロパティファイルの追記がどこに反映されているかを示します。ソースファイル上で、確かめておいてください。
[ edit.gspだけに加えられた変更 ]
- <title>タグの表記
<title><g:message code="default.edit.label" args="[entityName]" /></title>
- フォームの一番下にある「更新」ボタンのラベル
<g:actionSubmit class="save" action="update"
value="${message(code: 'default.button.update.label', default: 'Update')}"}");"/>
[ create.gspだけに加えられた変更 ]
- <title>タグの表記
<title><g:message code="default.create.label" args="[entityName]" /></title>
- フォームの一番下にある「更新」ボタンのラベル
<g:actionSubmitg:submitButton name="create" class="save"
value="${message(code: 'default.button.create.label', default: 'Create')}" />
その他にも、小さな変更がGSPファイルに加えられています。
「Grailsタグ」で書ける「コントロール」が増えました
5-16節 148ページの、リスト5-81をご覧ください。
変更前:
<input type="hidden" name="id" value="${wordinstance?.id}" /$gt;
これは、中に${...}でGroovyのコードを埋め込める、という以外は、ほとんどHTML形式での「非表示のパラメータ送信」です。
新しいバージョンでは、これを、「Grailsタグ」で表せるようになっています。
変更後:
<g:hiddenField name="id" value="${wordInstance?.id}" />
ちょっと簡単になりましたね。
同様、というか以下のほうが多いのですが、値を入力する「テキストフィールド」もGrailsタグで書けるようになりました。
変更前:
<input type="text" name="en" value="${wordinstance?.en}" />
変更後:
<g:textField name="en" value="${wordInstance?.en}" />
これらは、特にコードを修正する必要もないのでしょうが、せっかくですからなるべく使うようにすると、楽しい気持ちになれるでしょう。