職場実習17日目
引き続きGrails作業
前日の追記
日付をフォーマット指定で表示する方法について、社員の芳村さん(Grails/Groovyが得意な人)からアドバイスがあったので、ここに記しておく。
g:formatタグも必要ないらしい。次の1行で記述できる。
${userInstance?.since.format("yyyy年M月d日(E)")}
作りたいものを(MVCモデルを使って)1ページで描く
芳村さんから、まずは作りたいものを1ページで描くよう指示があったので、自分なりに考え、SS(作品)投稿サイトをMVCモデルに基づいてノートに描いてみる。
簡単に説明するとこんな感じになる。
- M(モデル)
- ドメイン:作品データ
- タイトル
- 作者名
- 内容
- 作成日
- 更新日
- ドメイン:作品データ
- V(ビュー)
- 作品リスト画面(list.gsp)
- 作品リスト
- 新規登録ボタン(Create)
- 作品選択ボタン(Show)
- 作品詳細画面(show.gsp)
- 作品内容表示テーブル
- 編集ボタン(Edit)
- 削除ボタン(Delete)
- 編集画面(edit.gsp)
- 作品内容変更フォーム
- 変更ボタン(Update)
- 削除ボタン(Delete)
- 新規登録画面(create.gsp)
- 作品内容入力フォーム
- 登録ボタン(Create)
- 作品リスト画面(list.gsp)
- C(コントローラー)
- 作品リスト取得
- 作品データ登録(Create)
- 作品データ取得(Read)
- 作品データ更新(Update)
- 作品データ削除(Delete)
Grailsを使ったアプリ設計の心得について教えてもらう
社員の山本さんから、Grailsアプリの作り方を色々教えてもらった。
山本さんのブログ:leftovers...
Grailsアプリの制作過程を記録したスライド:G* on GAE/J 挑戦編
まずはモデリングから
作品クラス(ssbbs.Story)の定義
package ssbbs class Story { static mapping = { id generator:'uuid.hex', params:[type:'string'] } String id // ID String title // タイトル String author // 作者名 String text // 本文 Date dateCreated // 作成日 Date lastUpdated // 最終更新日 static constraints = { title (nullable:false) author (nullable:false) text (nullable:false, maxSize:4000) dateCreated (display:false) lastUpdated (display:false) } }
ID生成部分と、作成日・更新日の非表示設定は、山本氏のソースをそのまま使っている。
これで、コントローラーとビューを生成したら、すぐにCRUDが揃ったデータベースの出来上がり。
ちなみに、ドメイン名を指定する時は、ssbbs.storyではなくssbbs.Storyと書かないと、grailsがドメインを見付けてくれず、コントローラーとビューが生成されないので注意。
リレーションを作る
次に、作者クラス(ssbbs.Author)を作り、作品クラスとの関係を定義する。
package ssbbs class Author { static mapping = { id generator:'uuid.hex', params:[type:'string'] } String id // ID String name String spell String loginId String loginKey String gender String email Date birthDay String address String telNo String celNo String hpUrl String comment Date dateCreated // 登録日 Date lastUpdated // 更新日 static hasMany = [stories : Story] static constraints = { name (sizeMax:20, nullable:false) spell (sizeMax:40, nullable:false) loginId (size:8..20, nullable:false, unique:true) loginKey (size:8..20, nullable:false) gender (inList:["男性", "女性"], nullable:true) email (email:true, nullable:false) address (maxSize:40, nullable:true) telNo (matches:"\\d{2,4}-\\d{2,4}-\\d{4}", nullable:true) celNo (matches:"\\d{2,4}-\\d{2,4}-\\d{4}", nullable:true) hpUrl (url:true, nullable:true) comment (maxSize:400, nullable:true) dateCreated (display:false) lastUpdated (display:false) } }
package ssbbs class Story { static mapping = { id generator:'uuid.hex', params:[type:'string'] } String id // ID String title // タイトル static belongsTo = [author:Author] // 作者 String text // 本文 Date dateCreated // 作成日 Date lastUpdated // 最終更新日 static constraints = { title (nullable:false) author (nullable:false) text (nullable:false, maxSize:4000) dateCreated (display:false) lastUpdated (display:false) } }
作者と作品の関係は、1:mの従属関係になる。ドメインを定義したら、それぞれコントローラーとビューを生成し直せば、作品データ入力時に作者名をリストから選べるようになり、作品画面から作者画面へリンクが張られ、作者画面には作品リストも表示され、それぞれの作品へリンクが張られる。とても便利。
グループドメインを考える
作品をグループに分ける際のシリーズ、ジャンルなどをインスタンスとして扱うグループドメインを考えてみた。
ソース化するとこうなる。
package ssbbs class Group { static belongsTo = Group, Author static mapping = { id generator:'uuid.hex', params:[type:'string'] } String id // ID String title // タイトル Author author // 作者 Group superGroup // 親グループ Hierarchy hierarchy // 階層 Date dateCreated // 作成日 Date lastUpdated // 最終更新日 static hasMany = [subGroups:Group] static constraints = { title (nullable:false) author (nullable:false) dateCreated (display:false) lastUpdated (display:false) } }
package ssbbs class Hierarchy { String name Integer rank static hasMany = [groups:Group] static constraints = { name (nullable:false, blank:false) rank (nullable:false) } }
また、作品がグループに属する事を考え、子グループをシンプルに定義するため、作品をグループの派生クラスとして定義し直してみる。
- ドメイン:作品(グループのサブクラス)
- 本文(制約:非NULL、4000字以内)
- 階層(制約:非表示)
ソース化するとこんな感じ。
package ssbbs class Story extends Group { String text // 本文 static constraints = { text (nullable:false, maxSize:4000) hierarchy (display:false) } }
ただ、グループは再帰的に他のグループを包含し、作品がサブクラス化されてしまうため、まだ扱い慣れていないGrails上での動作は保障できない。
よって、これらを実装するのは後回しとし、当面は作品と作者のみで最小限の実装を行う事にする。