ジェネレータ
ここでは、ジェネレータコマンド tspawn の説明をします。
スケルトンを生成
なによりもまず最初は、アプリケーションのスケルトンを作成しなければなりません。blogapp という名で作ってみましょう。
コマンドラインから次のコマンドを入力します。Windows の場合は、TreeFrog Command Prompt 上で実行してください。
$ tspawn new blogapp
実行すると、アプリケーションルートディレクトリをトップとしたディレクトリツリー、設定ファイル(ini)、プロジェクトファイル(pro) などが生成されました。ディレクトリはよく見かける名のものばかりです。ディレクトリとしては次のものが生成されます。
- controllers コントローラ
- models モデル
- views ビュー
- helpers ヘルパ
- config 設定ファイル置き場
- db データベースファイル置き場(SQLite)
- lib ライブラリ
- log ログファイル置き場
- plugin プラグイン置き場
- public 静的なファイル置き場(画像や Javascript)
- script スクリプト置き場
- test テスト用
- tmp 一時ディレクトリ(アップロード直後のファイルなど)
スキャフォールドを生成
スキャフォールドとは「足場」という意味で、ここでは CRUD 操作を行える基礎的な実装のことです。スキャフォールドに含まれるものは、コントローラ、モデル、ビューのソースファイルおよびプロジェクトファイル(pro)で、これらをベースに本格的な開発を始めるのが良いでしょう。
ジェネレータコマンドでスキャフォールドを作るためには、あらかじめデータベースにテーブルを定義し、設定ファイルにそのデータベース情報を記述する必要があります。では、テーブルを定義してみましょう。
例:
> CREATE TABLE blog (id INTEGER PRIMARY KEY, title VARCHAR(20), body VARCHAR(200));
データベースとして SQLite を使用する場合、データベースファイルはアプリケーションルートにある db ディレクトリへ作ってください。
設定ファイル(database.ini)にデータベース情報を設定します。ジェネレータコマンドは dev セクションに設定された情報を参照します。
[dev]
driverType=QMYSQL
databaseName=blogdb
hostName=
port=
userName=root
password=root
connectOptions=
設定一覧
項目 | 意味 | 備考 |
---|---|---|
driverType | ドライバ名 | 選択肢は次のとおり: - QDB2: IBM DB2 - QIBASE: Borland InterBase Driver - QMYSQL: MySQL Driver - QOCI: Oracle Call Interface Driver - QODBC: ODBC Driver - QPSQL: PostgreSQL Driver - QSQLITE: SQLite version 3 or above |
databaseName | データベース名 | SQLite の場合はファイルパスを指定します。 例: db/blogdb |
hostName | ホスト名 | 空欄の場合は localhost |
port | ポート番号 | 空欄の場合は デフォルトポート |
userName | ユーザ名 | |
password | パスワード | |
connectOptions | 接続オプション | 詳細は Qt ドキュメント参照: QSqlDatabase::setConnectOptions() |
データベースドライバが Qt SDK に組み込まれていないとデータベースへアクセスできません。もし組み込まれていなければ、FAQ を参照して組み込んでください。あるいは、ダウンロードページからデータベースドライバをダウンロードし、組み込んでください。
そうしてからジェネレータコマンドを実行すると、足場が生成されます。コマンドは必ずアプリケーションルートディレクトリで実行してください。
$ cd blogapp
$ tspawn scaffold blog
driverType: QMYSQL
databaseName: blogdb
hostName:
Database open successfully
created controllers/blogcontroller.h
created controllers/blogcontroller.cpp
:
結論: データベースにスキーマを定義し、ジェネレータコマンドで足場を作れ。
ファイルとディレクトリ構成は次のとおり。
$ tree
.
├── CMakeLists.txt
├── appbase.pri
├── blogapp10.pro
├── cmake
│ ├── CacheClean.cmake
│ └── TargetCmake.cmake
├── config
│ ├── application.ini
│ ├── cache.ini
│ ├── database.ini
│ ├── development.ini
│ ├── internet_media_types.ini
│ ├── logger.ini
│ ├── mongodb.ini
│ ├── redis.ini
│ ├── routes.cfg
│ └── validation.ini
├── controllers
│ ├── CMakeLists.txt
│ ├── applicationcontroller.cpp
│ ├── applicationcontroller.h
│ ├── blogcontroller.cpp
│ ├── blogcontroller.h
│ └── controllers.pro
├── db
│ └── dbfile
├── helpers
│ ├── CMakeLists.txt
│ ├── applicationhelper.cpp
│ ├── applicationhelper.h
│ └── helpers.pro
├── lib
├── log
├── models
│ ├── CMakeLists.txt
│ ├── blogservice.cpp
│ ├── blogservice.h
│ ├── models.pro
│ ├── mongoobjects
│ ├── objects
│ │ ├── blog.cpp
│ │ └── blog.h
│ └── sqlobjects
│ └── blogobject.h
├── plugin
├── public
│ ├── css
│ ├── images
│ └── js
├── script
├── sql
├── test
├── tmp
└── views
├── CMakeLists.txt
├── _src
│ └── _src.pro
├── blog
│ ├── create.erb
│ ├── index.erb
│ ├── save.erb
│ └── show.erb
├── layouts
├── mailer
├── partial
└── views.pro
テーブル名とモデル名/コントローラ名の関係
ジェネレータが生成するクラスの名前はテーブル名に基づいて決められ、次のようなルールになります。
テーブル名 モデル名 コントローラ名 Sqlオブジェクト名
blog_entry → BlogEntry BlogEntryController BlogEntryObject
つまり、モデル名ではアンダースコアが消えて、その次の文字が大文字になります。
単語の単数形/複数形の話は全く考える必要がありません。
ジェネレータのサブコマンド
tspawn コマンドの usage です。
$ tspawn -h
usage: tspawn <subcommand> [args]
Type 'tspawn --show-drivers' to show all the available database drivers for Qt.
Type 'tspawn --show-driver-path' to show the path of database drivers for Qt.
Type 'tspawn --show-tables' to show all tables to user in the setting of 'dev'.
Type 'tspawn --show-collections' to show all collections in the MongoDB.
Available subcommands:
new (n) <application-name>
scaffold (s) <table-name> [model-name]
controller (c) <controller-name> action [action ...]
model (m) <table-name> [model-name]
helper (h) <name>
usermodel (u) <table-name> [username password [model-name]]
sqlobject (o) <table-name> [model-name]
mongoscaffold (ms) <model-name>
mongomodel (mm) <model-name>
websocket (w) <endpoint-name>
api (a) <api-name>
validator (v) <name>
mailer (l) <mailer-name> action [action ...]
delete (d) <table-name, helper-name or validator-name>
サブコマンドとして controller, model, sqlobject を指定すると、それぞれ、コントローラだけ、モデル(SqlObject 含む)だけ、SqlObject だけを生成することができます。
~~ コラム ~~
TreeFrog には、DB スキーマの変更とその差分管理をするための仕組みであるマイグレーション機能がありません。必要に応じて、DBスキーマのマイグレーションツールを別途使用することお勧めします。
命名規約
TreeFrog にはファイル名やクラス名の命名規約があります。ジェネレータを使うと、以下の規約でファイルやクラスが生成されます。
コントローラの命名規約
コントローラのクラス名は、「テーブル名+ Controller」となります。常に大文字で始まり、単語の区切りの’_‘(アンダースコア)を消し、その区切りの先頭文字を大文字にします。例えば、次のようなクラス名になります。
- BlogController
- EntryCommentController
これらのファイルは、controllers ディレクトリに保存されます。その際のファイル名は、クラス名を全て小文字にして、拡張子(.h と .cpp)をつけたものになります。
モデルの命名規約
モデルのクラス名は、コントローラと同様に常に大文字で始まり、単語の区切りの’_‘(アンダースコア)を消し、その区切りの先頭文字を大文字にします。例えば、次のようなクラス名になります。
- Blog
- EntryComment
これらのファイルは、models ディレクトリに保存されます。コントローラと同様に、ファイル名はモデル名を全て小文字にして、拡張子(.h と .cpp)をつけたものになります。
Rails のように単語の単数形・複数形の変換はしません。
ビューの命名規約
ビューのテンプレートは、全て小文字で「アクション名+拡張子」というファイル名で、「views/コントローラ名」 ディレクトリに生成されます。拡張子は、テンプレートシステムによって変わります。
また、ビューをビルドすると、テンプレートを C++ コードに変換し views/_src ディレクトリにソースファイルを出力します。それらをコンパイルして、ビューの共有ライブラリが作られます。
CRUD
CRUD とは、Web アプリケーションにおける主要な4つの機能のことで、「Create (生成)」 「Read (読込)」 「Update (更新)」 「Delete (削除)」の頭文字をとっています。 ジェネレータコマンドで足場を作成すると、次の命名でコードを生成します。
CRUD 対応表
アクション | モデル | ORM | SQL | |
---|---|---|---|---|
C | create | create() [static] create() |
create() | INSERT |
R | index show |
get() [static] getAll() [static] |
find() | SELECT |
U | save | save() update() |
update() | UPDATE |
D | remove | remove() | remove() | DELETE |
T_CONTROLLER_EXPORT マクロについて
ジェネレータで作成したコントローラクラスには、T_CONTROLLER_EXPORT というマクロが追加されています。これは何なのでしょう。
Windows では、コントローラはまとめて1つの DLL になりますが、これらのクラスや関数を外部から利用可能にするために、__declspec(dllexport) というキーワードを付けて定義する必要があるのです。T_CONTROLLER_EXPORT マクロは、このキーワードに置換されます。
Mac OS X や Linux では、不要なキーワードなので T_CONTROLLER_EXPORT には何も定義されていません。
#define T_CONTROLLER_EXPORT
このようにすることで、同じソースコードが複数のプラットフォームに対応できているのです。