torutkのブログ

ソフトウェア・エンジニアのブログ

「Grailsをマスターする:GROM:おかしな名前の真面目な技術」を読みながら動かしてみる

Grails をマスターする: GORM: おかしな名前の真面目な技術の記事に沿ってGrailsの習得を進めます。

id:torutk:20090711:p2の続きです。

ドメインクラスAirlineの追加

先に作成したドメインクラスTripと1:多の関係となるAirlineクラス作成します。ドメインクラスの作成は記事中に方法は記載ないですが、前回と同じコマンドでよさそうです。

+------+ 1   * +---------+
| Trip +-------+ Airline |
+------+       +---------+
grails create-domain-class Airline の実行
trip-planner$ grails create-domain-class Airline
Welcome to Grails 1.1.1 - http://grails.org/
Licensed under Apache Standard License 2.0
Grails home is set to: /home/torutk/grails-1.1.1

Base Directory: /home/torutk/work/trip-planner
Running script /home/torutk/grails-1.1.1/scripts/CreateDomainClass.groovy
Environment set to development
Created DomainClass for Airline
Created Tests for Airline
trip-planner$ 
grails-app/domain/Airline.groovyの編集
class Airline {
    static constraints = {
    }

    static hasMany = [trip:Trip]

    String name
    String url
    String frequentFlyer
    String notes
}
grails-app/domain/Trip.groovyの編集

Airlineへの1の関連を追加します。

class Trip {
    ...
    Airline airline
}

Airlineのコントローラ追加

ドメインクラスを作成するときは、grails create-domain-class XXX と実行したので、コントローラを作るコマンドもないか?と気になって調べてみました。

grailsコマンドのターゲット一覧
trip-planner$ grails help
    :
Available Targets (type grails help 'target-name' for more info):
grails bootstrap
grails bug-report
grails clean
grails compile
grails console
grails create-app
grails create-controller
grails create-domain-class
grails create-filters
grails create-integration-test
grails create-plugin
grails create-script
grails create-service
grails create-tag-lib
grails create-unit-test
grails doc
grails generate-all
grails generate-controller
grails generate-views
grails help
grails init
grails install-plugin
grails install-templates
grails list-plugins
grails package
grails package-plugin
grails plugin-info
grails release-plugin
grails run-app
grails run-war
grails schema-export
grails set-proxy
grails set-version
grails shell
grails stats
grails test-app
grails uninstall-plugin
grails upgrade
grails war
trip-planner$

コントローラを生成するコマンドは、名前から類推すると、以下の2つと思われます。

  • create-controller
  • generate-controller

generate の方は、前回generate-allでviewとcontrollerを生成したもののcontroller部分だけを生成すると推測します。たぶん、ごっそり実装が生成されますが、今回はscaffold記述だけ書くので、create の方を実行してみようと思います。

grails create-controller Airline の実行
trip-planner$ grails create-controller Airline
    :
Base Directory: /home/torutk/work/trip-planner
Running script /home/torutk/grails-1.1.1/scripts/CreateController.groovy
Environment set to development
Created Controller for Airline
    [mkdir] Created dir: /home/torutk/work/trip-planner/grails-app/views/airline
Created Tests for Airline
trip-planner$ 

生成されたファイルは以下となります。

./test/unit/AirlineControllerTests.groovy
./grails-app/controllers/AirlineController.groovy

AirlineControllerの内容は以下となります。

class AirlineController {

    def index = { }
}

前回、grails generate-all で生成したコントローラと違って、やはり実装はまったく生成されていません。

AirlineController.groovyの編集

scaffold指定を記述します。

class AirlineController {

    def scaffold = Airline
}

サーバの実行

trip-planner$ grails -Dserver.port=8087 run-app
   :
Server running. Browse to http://localhost:8087/trip-planner

Airline選択のコンボボックス表示をIDでなく名前にする

AirlineクラスにtoString()メソッドを追記

class Airline {
  :
}

Airlineの各プロパティの表示順序を制御する

デフォルトのscaffoldでは、プロパティは画面上でアルファベット順に表示されます。好みの順序にするには、ドメインクラスにstatic constraintsで並び順を指定します。

class Airline {
    static constraints = {
        name()
        url()
        frequentFlyer()
        notes()
    }
    :

Airlineのプロパティ入力検査(validation)

ドメインクラスAirlineのstatic constraintsに検証ルールを追記します。

class Airline {

    static constraints = {
        name(blank:false, maxSize:100)
        url(url:true)
        frequentFlyer(blank:true)
        notes(maxSize:1500)
    }
    :

nameは、未入力をエラーとします。また、100文字以上は入力できません。

  • Firefoxでは以下の振る舞いをしています
    • 英数字(ASCII文字)だと、100文字を越える入力ができない
    • 漢字だと、100文字を越えて入力ができるがCreateすると超過分が切り落とされる

urlは、URLの書式でないとCreate時にエラーとなります。
notesは、入力欄が大きくなります。

ちなみにエラーを出してみると、以下のメッセージとなります。(日本語となっていた)

  • [class Airline]クラスのプロパティ[name]の空白は許可されません。
  • クラス[class Airline]プロパティ[url]の値[f]は、URLではありません。

はまり事

同じ名前のアプリケーションを複数ディレクトリで作成・実行してはいけない

trip-plannerディレクトリを別な場所へ丸ごとコピーして、データベースを別なものに変更して実験していました。
そのまま、元のディレクトリでサーバを実行しようとしたところ、DataSourceに記述していないデータベースへ接続しにいってエラーとなってしまいました。

Grailsは、ホームディレクトリ下の$HOME/.grails/1.1.1/の下に、プロジェクト名ごとにディレクトリを作ってgroovy〜コンパイルしたJavaのclassファイルなどを置いています。

実験でいじったプロジェクトは、ディレクトリだけコピーしたもののプロジェクト名は一緒だったので、$HOME/.grails/1.1.1/下のディレクトリは同じ場所を使用してしまい、不整合が発生したものです。

grailsターゲット一覧を見ると、cleanがあるので、これを実行し、$HOME/.grails/1.1.1/trip-planner下の生成物をいったん削除してからサーバを起動したら、うまくいきました。

trip-planner$ grails clean
   :
trip-planner$ grails run-app
   :