前へ | 次へ |
def fujiInstance = new Fuji(params)paramsは配列です。その中味は、
def fujiInstance = new Fuji()
そしたら、まずそろっているだけのパラメータを喰わせます。パラメータの一部だけを喰わせる方法はいろいろありますが、「itemcodedataのプロパティだけハズす」というのは以下の方法です。
bindData(fujiInstance,params,[exclude:"itemcodedata"])bindDataはドメインクラスではなくControllerクラスに定義された関数です。ここではFujiControllerの実行時オブジェクトが呼び出すことになるので、呼び出し元は省略されます。パラメータを喰わせようという相手は、bindDataメソッドの第1番目の引数になります。2番目の引数がparamsで、3番目が条件を配列に入れたものです。
一方、いよいよパラメータitemcodeをもとに、ItemCodeオブジェクトを検索します。これは以下のようにします。
fujiInstance.itemcodedata=ItemCode.findByItemcode(params.itemcode)findByItemcodeというメソッドに注目してください。findByItemCodeではありません。ItemCodeクラスのパラメータitemcodeが「キャメルケース」のルールに乗っかって最初の1文字だけがIと大文字になったのです。
おおっとぅ。得られるのは検索されたオブジェクトの配列なんじゃないかと思った人は思慮深い人です。ワタシもたった今思いました。でもGrailsはさすがです。1個のデータを求めて検索したのに配列が得られてグハァッとかなる場合が多いことを知っているのですね。findByナントカメソッドでは、見つかった最初のオブジェクトが得られます。見つかったオブジェクトの配列を得るにはfindAllByナントカになるのです。
見つかったオブジェクトが、fujiInstanceのプロパティitemcodedataの値になります。これは上記のように直にfujiInstance.itemcodeと書いちゃって構いません。Javaやって長い方はこういう直接のアクセスはお好きでないかも知れませんが、これはGroovyの書き方だからで、コンパイルされて最終的にJavaプログラムになるときにはちゃんとsetItemcodeみたいな礼儀正しい方法になっているはずですから安心してください。 これでfujiInstanceは保存可能になりました。あとは元のコードの処理に任せます。そこでsaveメソッドの全文は以下のようになります。
def save = { def fujiInstance = new Fuji() bindData(fujiInstance,params,[exclude:"itemcodedata"]) fujiInstance.itemcodedata=ItemCode.findByItemcode(params.itemcode) //このあとは元のコードのまま if (fujiInstance.save(flush: true)) {.....さてサーバは再起動しなくても大丈夫。FujiのCreateページに新規データを入れます。ただーし、今はまだ「すでにItemCodeに登録してあるコード」を入れてください。たとえば今の例では「3239」を「ヨーグルト」として登録してあるので、Itemcode「3239」を入れて、価格Priceに「128」を入れて、Pdateは本日のまんまでもいいですしテキトーな期日にしてもいいので、値がそろったら運命の「Create」ボタンを押すーッ。
エラーが出たらヴァナタの負け。ていうかsaveメソッドを確認してください。正しく書き変わってあればShowページに切り替わります。
これでコントローラの編集が成功したことがわかりました。次はShowページの「idが1のItemCodeオブジェクト」という表示を、「ヨーグルト」に変更する作業です。つまり、そのオブジェクトの「itemname」の値を表示させるのです。 FujiのShow.gspを編集しましょう。
<td valign="top" class="value"> <g:link controller="itemCode" action="show" id="${fujiInstance?.itemcodedata?.id}"> ${fujiInstance?.itemcodedata?.encodeAsHTML()}</g:link> </td>まず、全体が<td>タグで挟まれていますから、表のセルのひとつです。でもホントに表を使いたいわけじゃなくて、項目や値をまっすぐ揃えて配置するのに表の書式を使っているだけです。
<td>タグの中には<g:link>タグがあります。Grailsで「リンク」を表すタグです。元はitemcodedataを表示するこの部分、クリックするとコイツが該当するItemCodeオブジェクトのShowページにリンクするようになっています。だから「ItemCode:1」と書かれていてこりゃ何じゃと思っても,クリックすればその内容がわかるというしくみです。
しかしいちいちクリックして内容を見る必要をなくしましょう。要は買ったものがナニかわかればいいのです。つまり商品名、itemnameプロパティーです。
「リンク」を表すタグに挟まれている太字の部分が、Showページに「表示される」内容です。「?」がついているのは、空でなければという安全措置です。「ヌル(とかニルとか)のデータがメソッドを呼ぶことはできません」というエラーが表示されてアプリケーションがストップしたのにムカーという思いをしたことは多いのではないでしょうか。Grailsでは「?」のおかげで、ヌルデータになった時点で黙って処理をやめてくれます。
また、「encodeAsHTML」は「文字列にタグが入っていてもそのまんま表示する」という、いわゆる不正タグ注入防止のアレです。ワタシも、なんでそれが「HTMLとしてエンコードする」というメソッド名になるのかうんと悩んだんですけど、こういうことらしいですね。
文字列に<が入っていたらアンパサンドltセミコロンに「エンコード」するそんなわけで、ココはこのように書いてやれば、該当するItemCodeオブジェクトの「商品名」を表示することができます。
fujiInstance?.itemcodedata?.itemcodename.encodeAsHTML()
その上の行が、「ラベル」ですが、「Itemcode」という文字が表示されるようになっています。これ、「Itemname」に直しておきます。
<td valign="top" class="name"><g:message code="fuji.itemcodedata.label" default="Itemname" />
以上、今度は作成したあと、入力した商品コードからちゃんと商品名が検索されて表示されます。といってもまだ、ItemCodeデータとして登録済みの商品コードを慎重に選んでください。
index.gspの中で、ItemCodeオブジェクトのidが表示されている列はこのように書いてあります。
<td>${fieldValue(bean: fujiInstance, field: "itemcodedata")}</td>太字の部分を"itemcodedata.itemname"に直します。
ついてるラベルは、以下のように書いてあります。
<th><g:message code="fuji.itemcodedata.label" default="Itemcodedata" /></th>こちらは、太字のItemcodedataをItemnameに直します。
これで、「ItemCodeに登録済みの商品コードであれば、Fujiのほうではコードを入力すれば商品名がわかる」システムになりました。
次は、「ItemCodeに登録してない商品は、Fujiから登録」できるようにしましょう。次へ