前回に引き続きjavascriptMVC入門です。
2:モデルの作成
MVCのM、モデルを作成します。
javascriptMVCの場合、Railsなんかと同じくCRUD操作も担当しています。
今回はメモを表すモデルを作成します。
モデル作成の際はmodelジェネレータを使用します。
引用:本家ドキュメント
http://javascriptmvc.com/docs.html#!steal.generate
model
Creates a jQuery.Model and test files.
js jquery/generate/model App.Models.Name [TYPE] [OPTIONS]
- App.Models.Name - The namespaced name of your model. For example, if your model is named Cookbook.Models.Recipe, the generator will createcookbook/models/recipe.js.
モデル名は以下で指定するとのことです。
[ルート名前空間].Models.[モデル名]
モデル名は「Memo」にします。
前回の通り名前空間は「SimpleMemo」となりますので、実行するのは以下のコマンドとなります。
$./js jquery/generate/model SimpleMemo.Models.Memo
実行すると、
$./js jquery/generate/model SimpleMemo.Models.Memo
simple_memo/models/memo.js
simple_memo/test/qunit/memo_test.js
simple_memo/models/models.js (steal added)
simple_memo/test/qunit/qunit.js (steal added)
simple_memo/fixtures/fixtures.js (code added)
こんな結果が出力されます。
モデルオブジェクトに加えて、テスト用コードや、モデルをロードするためのコードが追記されます。
早速確認してみましょう。
http://localhost/jmvc/simple_memo/qunit.html
おなじみ?のqunitの画面が表示されますね。
では気になるモデルの中身を確認してみましょう。
simple_memo/models/memo.js
steal('jquery/model', function(){
$.Model('SimpleMemo.Models.Memo',
/* @Static */
{
findAll : "/memos.json",
findOne : "/memos/{id}.json",
create : "/memos.json",
update : "/memos/{id}.json",
destroy : "/memos/{id}.json"
},
/* @Prototype */
{});
なんだかクラス定義っぽいのが並んでますね。
順番に解説していきます。
まず一番外側のsteal関数ですが、前回の説明の通りファイルの読み込みと
渡された関数の実行を行います。
'jquery/model'という指定がファイルパスとなります。
このファイル読み込み後に、もう一つの引数である関数が実行されます。
<補足>
前回は説明を省略しましたが、このsteal関数は'jquery/model'みたいな指定をすると、
自動的にファイルパスへと変換してくれます。
この辺のルール/お作法は改めて説明します。
では関数の中身をみてみましょう。
以下の関数を実行しています。
$.Model('モデル名(名前空間含む)' , staticなメンバー, インスタンスのメンバー);
これはJavaScriptMVCで提供されているクラス定義用の関数です。
実際には$.Modelは$.Classを継承しています。
JavaScriptMVCのクラス定義の特徴としては
・Staticメンバーの継承
・イントロスペクションのサポート
・名前空間への対応
・コンストラクタ用関数の提供
・コールバック関数の簡易な作成
などがあります。
詳細は本家ドキュメントを参照してください。
http://javascriptmvc.com/docs.html#!jQuery.Class
http://javascriptmvc.com/docs.html#!jQuery.Model
$.Model関数の第2、3引数にオブジェクトを渡すことで
クラス定義を行ってくれています。
staticメンバーにfindAllやらfindOneやらが定義されていますが、
これは後回しにして、とりあえずメンバーの追加をしてみます。
追加するのはメモ本文を表すプロパティ「memoText」関数です。
引数なしで実行するとメモ本文を取得し、
引数に文字列を指定すると、メモ本文が設定されます。
まずはテストを追加しましょう。
modelジェネレータで作成された「test/qunit/memo_test.js」を開きます。
simple_memo/test/qunit/memo_test.js
steal("funcunit/qunit", "simple_memo/fixtures", "simple_memo/models/memo.js", function(){
module("Model: SimpleMemo.Models.Memo")
test("findAll", function(){
expect(4);
stop();
SimpleMemo.Models.Memo.findAll({}, function(memos){
ok(memos)
ok(memos.length)
ok(memos[0].name)
ok(memos[0].description)
start();
});
})
test("create", function(){
expect(3)
stop();
new SimpleMemo.Models.Memo({name: "dry cleaning", description: "take to street corner"}).save(function(memo){
ok(memo);
ok(memo.id);
equals(memo.name,"dry cleaning")
memo.destroy()
start();
})
})
test("update" , function(){
expect(2);
stop();
new SimpleMemo.Models.Memo({name: "cook dinner", description: "chicken"}).
save(function(memo){
equals(memo.description,"chicken");
memo.update({description: "steak"},function(memo){
equals(memo.description,"steak");
memo.destroy();
start();
})
})
});
test("destroy", function(){
expect(1);
stop();
new SimpleMemo.Models.Memo({name: "mow grass", description: "use riding mower"}).
destroy(function(memo){
ok( true ,"Destroy called" )
start();
})
})
})
すでに単体テストが記載されています。
ここにテストケースを一つ追加します。
simple_memo/test/qunit/memo_test.js
test("class_define", function(){
expect(3);
var memo = new SimpleMemo.Models.Memo();
ok(memo.getMemoText() , "Memo getMemoText defined");
ok(memo.setMemoText() , "Memo setMemoText defined");
memo.setMemoText("test");
ok(memo.getMemoText() == "test" , "Memo memoText setted/getted");
})
getter/setterの確認となっています。
実行するとエラーになりますね。
早速実装します。
simple_memo/models/memo.js
steal('jquery/model', function(){
$.Model('SimpleMemo.Models.Memo',
/* @Static */
{
findAll : "/memos.json",
findOne : "/memos/{id}.json",
create : "/memos.json",
update : "/memos/{id}.json",
destroy : "/memos/{id}.json"
},
/* @Prototype */
{
getMemoText : function(){
return this.memoText;
},
setMemoText : function(val){
this.memoText = val;
}
});
});
グリーンバーを獲得できましたね。
続きは後ほど編集します、、、