ジェネレータ

ここでは、ジェネレータコマンド 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

このようにすることで、同じソースコードが複数のプラットフォームに対応できているのです。