Tower.jsは、Ruby on railsやCakePHPの人には、すぐに理解できるパッケージでありましょう。ドキュメントも途中のようですが、敷居は低そうです。
前回のエントリー「さらばExpressよ!Tower.jsを試すの巻」に続き、今回は Tower.jsの全体像を見て行きたいと思います。
Tower.jsでは膨大なパッケージが使われていますが、実際、重要そうなモジュールはこんな感じかな、と。
Tower.Applicationクラス
アプリケーションの定義クラス。各アプリはTower.Applicationを継承して設定してきます。
tower new hogehogeコマンドで自動的に生成されます。Expressと比較してコードが劇的に減っているのがわかります。そして美しい。
# config/application.coffee
class App extends Tower.Application
@configure ->
@use "favicon", Tower.publicPath + "/favicon.ico"
@use "static", Tower.publicPath, maxAge: Tower.publicCacheDuration
@use "profiler" if Tower.env != "production"
@use "logger"
@use "query"
@use "cookieParser", Tower.session.secret
@use "session", Tower.session.key
@use "bodyParser"
@use "csrf"
@use "methodOverride", "_method"
@use Tower.Middleware.Agent
@use Tower.Middleware.Location
@use Tower.Middleware.Router
module.exports = global.App = App
Tower.Modelクラス
モデルを定義するクラス。各モデルはTower.Modelを継承して設定してきます。モデル同士の関連(belongsTo, hasMany)もココで定義します。ちょっとした変換もここで。
tower generate scaffold <モデル名>で生成できます。
# app/models/post.coffee
class App.Post extends Tower.Model
@field "title"
@field "body"
@field "tags", type: ["String"], default: []
@field "slug"
@belongsTo "author", type: "User"
@hasMany "comments", as: "commentable"
@before "validate", "slugify"
slugify: ->;
@set "slug", @get("title").replace(/^[a-z0-9]+/g, "-").toLowerCase()
Tower.Routeクラス
ルーティング定義。セッションの生成、破棄もココ。
# config/routes.coffee
Tower.Route.draw ->
@match "/login", "sessions#new", via: "get", as: "login"
@match "/logout", "sessions#destroy", via: "get", as: "logout"
@resources "posts", ->
@resources "comments"
@namespace "admin", ->
@resources "users"
@resources "posts", ->
@resources "comments"
@constraints subdomain: /^api$/, ->
@resources "posts", ->
@resources "comments"
@match "(/*path)", to: "application#index", via: "get"
ビュー
描画部分を定義。CoffeeKupで記述。Bootstrap2に対応!
tower generate view <ビュー名> コマンドで生成できます。
# app/views/posts/new.coffee
formFor "post", (f) ->
f.fieldset (fields) ->
fields.field "title", as: "string"
fields.field "body", as: "text"
f.fieldset (fields) ->
fields.submit "Submit"
Layout。指定しなければ、このレイアウトでラップされる。partialだけ書けば良い。
# app/views/layouts/application.coffee
doctype 5
html ->
head ->
meta charset: "utf-8"
title t("title")
meta name: "description", content: t("description")
meta name: "keywords", content: t("keywords")
meta name: "robots", content: t("robots")
meta name: "author", content: t("author")
csrfMetaTag()
appleViewportMetaTag width: "device-width", max: 1, scalable: false
stylesheets "lib", "vendor", "application"
javascriptTag "https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"
javascripts "vendor", "lib", "application"
body role: "application", ->
if hasContentFor "templates"
yield "templates"
nav id: "navigation", role: "navigation", ->
div class: "frame", ->
partial "shared/navigation"
header id: "header", role: "banner", ->
div class: "frame", ->
partial "shared/header"
section id: "body", role: "main", ->
div class: "frame", ->
yields "body"
aside id: "sidebar", role: "complementary", ->
if hasContentFor "sidebar"
yields "sidebar"
footer id: "footer", role: "contentinfo", ->
div class: "frame", ->
partial "shared/footer"
if hasContentFor "popups"
aside id: "popups", ->
yields "popups"
if hasContentFor "bottom"
yields "bottom"
Tower.Controllerクラス
モデルとビューを操作するコントローラクラス。あるアクションに対してモデルとビューをどうするか定義。モデリングにもよるけど、1つのモデルに対して大体1個定義。
tower generate controller コマンドで生成できます。
# app/controllers/postsController.coffee
class App.PostsController extends Tower.Controller
index: ->
App.Post.all (error, posts) =>
@render "index", locals: posts: posts
new: ->
@post = new App.Post
@render "new"
create: ->
@post = new App.Post(@params.post)
super (success, failure) ->
@success.html -> @render "posts/edit"
@success.json -> @render text: "success!"
@failure.html -> @render text: "Error", status: 404
@failure.json -> @render text: "Error", status: 404
show: ->
App.Post.find @params.id, (error, post) =>
@render "show"
edit: ->
App.Post.find @params.id, (error, post) =>
@render "edit"
update: ->
App.Post.find @params.id, (error, post) =>
post.updateAttributes @params.post, (error) =>
@redirectTo action: "show"
destroy: ->
App.Post.find @params.id, (error, post) =>
post.destroy (error) =>
@redirectTo action: "index"
データベースの定義
どのデータベースを使うか。開発用、テスト用、デモ用、本番用など用途に応じて定義可能。
# config/databases.coffee
module.exports =
mongodb:
development:
name: "app-development"
port: 27017
host: "127.0.0.1"
test:
name: "app-test"
port: 27017
host: "127.0.0.1"
staging:
name: "app-staging"
port: 27017
host: "127.0.0.1"
production:
name: "app-production"
port: 27017
host: "127.0.0.1"
多言語の定義
日本語の場合、たぶんjp.coffeeで定義。多言語化は始めからやっておくと吉。
# config/locales/en.coffee
module.exports =
hello: "world"
forms:
titles:
signup: "Signup"
pages:
titles:
home: "Welcome to %{site}"
posts:
comments:
none: "No comments"
one: "1 comment"
other: "%{count} comments"
messages:
past:
none: "You never had any messages"
one: "You had 1 message"
other: "You had %{count} messages"
present:
one: "You have 1 message"
future:
one: "You might have 1 message"
こんなもんかな。
全体的にコードが美しいです。ドキュメントはまだまだ足りませんが、Rails-erやCakePHP-erには読まなくとも大体は理解できるようになっているので、学習時間が少なくて済むのがいいところでしょうか。
0 件のコメント:
コメントを投稿