web-dev-qa-db-ja.com

コレクションを持つBackbone.jsモデル

2つのモデルと1つのコレクションがあります。 JobSummaryはモデル、JobSummaryListJobSummaryアイテムのコレクションであり、JobSummarySnapshotを含むJobSummaryListモデルがあります。

JobSummary = Backbone.Model.extend({});

JobSummaryList = Backbone.Collection.extend({
    model: JobSummary
});

JobSummarySnapshot = Backbone.Model.extend({
    url: '/JobSummaryList',

    defaults: {
        pageNumber: 1,
        summaryList: new JobSummaryList()
    }
});

fetchオブジェクトでJobSummarySnapshotを呼び出すと、すべてが取得されます... summaryListコレクションを移動する場合を除き、すべてobject型であり、 JobSummaryではありません。

defaultsオブジェクト以外では、summaryListJobSummaryList型である必要があることを知らないため、これは理にかなっていると思います。各項目を調べてJobSummaryオブジェクトに変換できますが、手動で実行しなくても実行できる方法があることを望んでいました。

ここに私のテストコードがあります(動作中 jsfiddle here ):

var returnData = {
    pageNumber: 3,
    summaryList: [
        {
        id: 5,
        name: 'name1'},
    {
        id: 6,
        name: 'name2'}
    ]
}; 

var fakeserver = sinon.fakeServer.create();
fakeserver.respondWith('GET', '/JobSummaryList', [200,
{
    'Content-Type': 'application/json'},
                                JSON.stringify(returnData)]);

var callback = sinon.spy();


var summarySnapshot = new JobSummarySnapshot();
summarySnapshot.bind('change', callback);

summarySnapshot.fetch();
fakeserver.respond();

var theReturnedList = callback.getCall(0).args[0].attributes.summaryList;

_.each(theReturnedList, function(item) {
    console.log('Original Item: ');
    console.log(item instanceof JobSummary); // IS FALSE
    var convertedItem = new JobSummary(item);
    console.log('converted item: ');
    console.log(convertedItem instanceof JobSummary); // IS TRUE
});

更新:解析関数をオーバーライドし、そのように設定できることがわかりました...今、これがあります:

JobSummarySnapshot = Backbone.Model.extend({
    url: '/JobSummaryList',

    defaults: {
        pageNumber: 1,
        summaryList: new JobSummaryList()
    },

    parse: function(response) {
        this.set({pageNumber: response.pageNumber});

        var summaryList = new JobSummaryList();
        summaryList.add(response.summaryList);

        this.set({summaryList: summaryList});
    }
});

これは今のところ機能します。誰かがコメントした場合に備えて、質問を開いたままにしてください。

37
Bryce Fischer

あなたのparse()関数はset()何もすべきではありません。属性を返すだけの方が良い習慣であり、Backboneがそれを設定します。例えば.

_parse: function(response) {
    response.summaryList = new JobSummaryList(response.summaryList);
    return response;
}
_

parse()から返されるものはすべて set()に渡されます です。

何も返さない(undefinedを返すようなもの)は、set(undefined)を呼び出すのと同じです。これにより、検証に合格しなかったり、カスタムvalidate()/set()メソッドはオブジェクトを取得することを想定しています。そのために検証またはset()メソッドが失敗した場合、Backbone.Model#fetch()に渡された_options.success_コールバックは呼び出されません。

また、これをより一般的にして、サーバー応答だけでなく他の場所からプレーンオブジェクトへのset() ingも影響を与えるように、代わりにset()をオーバーライドすることもできます。 :

_set: function(attributes, options) {
    if (attributes.summaryList !== undefined && !(attributes.summaryList instanceof JobSummaryList)) {
        attributes.summaryList = new JobSummaryList(attributes.summaryList);
    }
    return Backbone.Model.prototype.set.call(this, attributes, options);
}
_

また、 Backbone-relational を見つけることもできます。これにより、モデル内にネストされたコレクション/モデルの処理がはるかに簡単になります。

editset()メソッドから戻るのを忘れたため、コードが更新されました

56
shesek