gist

ラベル Matador の投稿を表示しています。 すべての投稿を表示
ラベル Matador の投稿を表示しています。 すべての投稿を表示

2012年3月25日日曜日

Hogan.jsを使ってみる

Hogan.jsは、Twitterで開発されたJavaScriptテンプレートエンジンです。2.5KBと軽量でシンプルな仕組みとなっています。Matadorで使われています。

「hogan」ではなく「Hogan.js」です。npm install時に注意。地味にハマりました。

$ npm install hogan.js
npm http GET https://registry.npmjs.org/hogan.js
npm http 304 https://registry.npmjs.org/hogan.js
hogan.js@2.0.0 ../node_modules/hogan.js

sample.coffee

hogan = require 'hogan.js'
template = hogan.compile "@{{name}}"

names = ['初音ミク', '鈴音リン', '鈴音レン']

names.map (vocaloid) ->
  template.render({name:vocaloid})

console.log 'VOCALOID: ' + names.join(' ') + '!' 

実行

$ coffee sample.coffee 
VOCALOID: 初音ミク 鈴音リン 鈴音レン!

{{hogehoge}} に template.render 関数で指定したオブジェクトのhogehogeキーの値が入ってきます。

2012年3月24日土曜日

Valentineを使ってみる

Valentineは、型チェックや関数のイテレーション、ウォーターフォールやキュー、並列処理などの機能を提供するJavaScriptライブラリです。ScalaやHaskell、F#のような関数型言語っぽく記述することもできるそうです。

Valentineは、Matadorの開発者 ded 氏が開発し、Matadorでもも使われています。

npmでインストールします。

$ npm install valentine
npm http GET https://registry.npmjs.org/valentine
npm http 304 https://registry.npmjs.org/valentine
valentine@1.5.1 ./node_modules/valentine

まずはサンプルを CoffeeScript で書いてみます。

sample.coffee

v = require "valentine"

a = v(["a", "b", "c"]).map (letter) ->
  letter.toUpperCase()
.join " "

console.log a

「文字a,b,cの配列をmap関数で一文字ずつ大文字に変換してスペースで結合する」を繋げて書けます。

実行してみます。

$ coffee sample.coffee 
A B C

Valentineのwaterfallを使ってみます。

waterfall.coffee

v = require "valentine"

v.waterfall ((callback) ->
  callback null, "提案", "却下"
),((a, b, callback) ->
  console.log a
  console.log b
  callback null, "酒"
),((c, callback) ->
  console.log c
  callback null, "二日酔い"
), (err, result) ->
  console.log result

waterwallは上から順番に実行してくれます。次の関数へ引数とコールバックを投げることで次々と実行されます。

$ coffee waterfall.coffee 
提案
却下
酒
二日酔い

キュー実行の queue や並列実行の parallel もあり便利なライブラリです。Matadorでも使われていますので、覚えていて損はないと思います。

2012年3月23日金曜日

Klassを使ってみる

Klassは、JavaScriptにもう少し使いやすいクラスの概念を持ち込めるライブラリです。

$ npm install klass

Person.js

var klass = require('klass')
var Person = klass(function (name) {
    this.name = name;
})
  .methods({
    sing:function() {
      console.log(this.name+' is singing');
    }   
  })  

module.exports = Person;

継承も使える

SuperHuman.js

var Person = require('./Person')
var SuperHuman = Person.extend(function (name) {
})
.methods({
  sing: function() {
    this.supr()
    this.fly()
  },  
  fly: function() {
    console.log(this.name + ' は空を飛ぶ')
  }
})

module.exports = SuperHuman;

main.js

var Person = require('./Person');
var SuperHuman = require('./SuperHuman');
var miku = new Person('初音ミク')
miku.sing();
  
var yazawa = new SuperHuman('矢沢永吉');
yazawa.sing();

実行結果。

$ node main.js 
初音ミク is singing
矢沢永吉 is singing
矢沢永吉 は空を飛ぶ

プライベートやスタティックも可能。いろんなフレームワークで使われているので、覚えていて損はないかと。

2012年3月19日月曜日

[Node.js] MatadorでMochaを使ったテストを書いてみる

Matadorでmochaを使ったテストをやってみます。

Matadorは前回のエントリーでインストールします。

[Node.js] Matador+CoffeeScriptの環境を構築する

テストフレームワークにMochaとshouldをインストールします。

$ npm install -g mocha should
$ matador init masamune
$ mkdir test

次にテストを書いてみます。モデルからやってみます。

Masamune.test.coffee

app = require('matador').createApp __dirname + '/../'
should = require 'should'

describe 'MasamuneModel', ->
  describe '生成', ->
    it '政宗モデルを生成できる', (done) ->
      MasamuneModel = app.getModel('Masamune', true)
      model = new MasamuneModel()
      should.exist model
      done()


テストを実行してみましょう。

$ mocha

  .

  ✖ 1 of 1 tests failed:

  1) MasamuneModel 生成 政宗モデルを生成できる:
     Error: Unable to find models/MasamuneModel
      at /Users/inouetomoyuki/Dropbox/Projects/node/matador_coffee_sample/node_modules/matador/src/matador.js:78:25
      at /Users/inouetomoyuki/Dropbox/Projects/node/matador_coffee_sample/node_modules/matador/src/matador.js:83:36
      at HTTPServer.getModel (/Users/inouetomoyuki/Dropbox/Projects/node/matador_coffee_sample/node_modules/matador/src/matador.js:201:12)
      at Context.<anonymous> (/Users/inouetomoyuki/Dropbox/Projects/node/matador_coffee_sample/test/MasamuneModel.test.coffee:12:29)
      at Test.run (/Users/inouetomoyuki/.nvm/v0.6.12/lib/node_modules/mocha/lib/runnable.js:143:15)
      at Runner.runTest (/Users/inouetomoyuki/.nvm/v0.6.12/lib/node_modules/mocha/lib/runner.js:272:10)
      at /Users/inouetomoyuki/.nvm/v0.6.12/lib/node_modules/mocha/lib/runner.js:316:12
      at next (/Users/inouetomoyuki/.nvm/v0.6.12/lib/node_modules/mocha/lib/runner.js:199:14)
      at /Users/inouetomoyuki/.nvm/v0.6.12/lib/node_modules/mocha/lib/runner.js:208:7
      at next (/Users/inouetomoyuki/.nvm/v0.6.12/lib/node_modules/mocha/lib/runner.js:157:23)
      at Array.0 (/Users/inouetomoyuki/.nvm/v0.6.12/lib/node_modules/mocha/lib/runner.js:176:5)
      at EventEmitter._tickCallback (node.js:192:40)

「MasamuneModelがありません」と怒られますので、作ってみます。Matadorのジェネレーターを使って生成してみます。

$ matador model Masamune
generating model Masamune
Successfully created ./app/models/MasamuneModel.js
$ js2coffee app/models/MasamuneModel.js > app/models/MasamuneModel.coffee
$ rm app/models/MasamuneModel.js 

もう一回実行してみます。

$ mocha

  .

  ✔ 1 tests complete (9ms)

テストが通りました。

もう少しだけテストを書いてみましょう。

app = require('matador').createApp __dirname + '/../'
should = require 'should'

describe 'MasamuneModel', ->
  describe '生成', ->
    it '政宗モデルを生成できる', (done) ->
      MasamuneModel = app.getModel('Masamune', true)
      model = new MasamuneModel()
      should.exist model
      done()
  describe '取得', ->
    it '伊達家の歴代を取得する', (done) ->
      MasamuneModel = app.getModel('Masamune', true)
      model = new MasamuneModel()
      model.findAll (err, dateList) ->
        dateList.length.should.eql 1
        dateList.should.eql ['伊達政宗']
        done()

実行してみます。

$ mocha

  ..

  ✖ 1 of 2 tests failed:

  1) MasamuneModel 取得 伊達家の歴代を取得する:
     TypeError: Object #<fn> has no method 'findAll'
      at Context.<anonymous> (/Users/inouetomoyuki/Dropbox/Projects/node/matador_coffee_sample/test/MasamuneModel.test.coffee:23:22)
      at Test.run (/Users/inouetomoyuki/.nvm/v0.6.12/lib/node_modules/mocha/lib/runnable.js:143:15)
      at Runner.runTest (/Users/inouetomoyuki/.nvm/v0.6.12/lib/node_modules/mocha/lib/runner.js:272:10)
      at /Users/inouetomoyuki/.nvm/v0.6.12/lib/node_modules/mocha/lib/runner.js:316:12
      at next (/Users/inouetomoyuki/.nvm/v0.6.12/lib/node_modules/mocha/lib/runner.js:199:14)
      at /Users/inouetomoyuki/.nvm/v0.6.12/lib/node_modules/mocha/lib/runner.js:208:7
      at next (/Users/inouetomoyuki/.nvm/v0.6.12/lib/node_modules/mocha/lib/runner.js:157:23)
      at Array.0 (/Users/inouetomoyuki/.nvm/v0.6.12/lib/node_modules/mocha/lib/runner.js:176:5)
      at EventEmitter._tickCallback (node.js:192:40)

findAllメソッドがないと怒られます。プロダクトコードを修正します。

app/models/MasamuneModel.coffee


module.exports = (app, config) ->
  app.getModel("Application", true).extend().methods({
    findAll:(callback) ->
      callback(null, ['伊達政宗'])
  }) 

テストを実行してみます。

$ mocha

  ..

  ✔ 2 tests complete (7ms)


無事通りました。

こんな感じでやっていけば、何とかなりそうです。テストコード内の1行目「app」の取得方法がかっこ悪いですが。

2012年3月18日日曜日

[Node.js] Matador+CoffeeScriptの環境を構築する

「Twitter生まれの軽量なMVCフレームワーク「Matador」を試してみた」で紹介した「Matador」がCoffeeScriptに対応したようです。

早速、環境を構築してみます。

MatadorとCoffeeScriptをグローバルインストールします。

$ npm install -g matador
$ npm install -g coffee-script

Matadorでアプリケーションの雛形を作成します。

$ matador init matador_coffee_sample
installing Matador into matador_coffee_sample
Success!
$ cd matador_coffee_sample
$

次にMatadorをローカルインストールします。

現在(2012/03/18)のところ、npm でインストールされる Matador@1.0.11-beta では CoffeeScript が動作しません。Githubからダウンロードしてインストールします。

$ cd node_modules
$ rm -r matador
$ git clone https://github.com/rcs/matador.git
$ cd matador
$ npm install

最後にアプリケーションの雛形で作成された js ファイルを CoffeeScript に一括で変換します。一括変換は、アプリケーションのルートディレクトリ(server.jsがあるディレクトリと同じ階層)で実行します。

$ cd ../..
$ pwd
/Users/inouetomoyuki/Dropbox/Projects/node/matador_coffee_sample

$ npm install -g js2coffee
$ for f in `find . -type f -name '*.js' ! -path '*/node_modules/*'`; do js2coffee $f > ${f%.*}.coffee && rm $f; done

$ tree app
app
├── config
│   ├── development.coffee
│   ├── production.coffee
│   └── routes.coffee
├── controllers
│   ├── ApplicationController.coffee
│   └── HomeController.coffee
├── models
│   ├── ApplicationModel.coffee
│   └── BaseModel.coffee
├── public
│   └── css
│       ├── directory.css
│       └── main.css
└── views
    ├── 404.html
    ├── admin
    │   ├── index.html
    │   └── partials
    │       └── helloworld.html
    ├── directory.html
    ├── index.html
    ├── layout.html
    └── partials
        └── helloworld.html

for f in ...の一行で一括変換しています。

$ for f in `find . -type f -name '*.js' ! -path '*/node_modules/*'`; do js2coffee $f > ${f%.*}.coffee && rm $f; done

実行して見ます。

$ coffee server.coffee 
matador running on port 3000

無事表示されました。

Expressでは、実装が進むにつれMVCがごちゃごちゃになりがちでした。かといってTower.jsは大きすぎて迷子に。Matadorが今のところ丁度いいフレームワークかと思います。CoffeeScript対応で普及にはずみがつきそうですね。