2

私はバックボーンにかなり慣れていないので、to do リストを処理する単純なスクリプトをテストしたいと考えていました。これまでに使用したコードは次のとおりです。

(function() {

    window.App = {
        Models: {},
        Collections: {},
        Views: {}
    };

    window.template = function(id) {
        return _.template($('#' + id).html());
    }

    App.Models.Task = Backbone.Model.extend({
        validate: function(attributes) {
            if ( !$.trim(attributes.title) ) {
                return 'Invalid title';
            }
        }
    });
    App.Collections.Tasks = Backbone.Collection.extend({
        model: App.Models.Task
    });
    App.Views.Task = Backbone.View.extend({
        tagName: 'li',
        template: template('taskTemplate'),
        initialize: function () {
            this.model.on('change', this.render, this);
            this.model.on('destroy', this.remove, this);
        },
        events: {
            'click .edit': 'editTask',
            'click .delete': 'destroy'
        },
        destroy: function() {
            if (confirm('Are you sure?')) {
                this.model.destroy();
            }
        },
        remove: function() {
            this.$el.remove();
        },
        editTask: function() {
            var newTaskTitle = prompt('New title:', this.model.get('title'));
            this.model.set('title', newTaskTitle, {validate: true});
        },
        render: function() {
            this.$el.html(this.template(this.model.toJSON()));
            return this;
        }
    });
    App.Views.AddTask = Backbone.View.extend({
        el: 'form#addTask',
        initialize: function() {

        },
        events: {
            'submit': 'submit'
        },
        submit: function(event) {
            event.preventDefault();
            var newTaskTitle = $(event.currentTarget).find('input[type=text]').val();
            var task = new App.Models.Task({ title: newTaskTitle });
            this.collection.add(task, {add: true, merge: false, remove: false});
        }
    });
    App.Views.Tasks = Backbone.View.extend({
        tagName: 'ul',
        initialize: function() {
            this.collection.on('add', this.addOne, this);
        },
        render: function() {
            this.collection.each(this.addOne, this);
            return this;
        },
        addOne: function(task) {
            var taskView = new App.Views.Task({ model: task });
            this.$el.append(taskView.render().el);
        }
    });

    var tasks = new App.Collections.Tasks([
        {
            title: 'Go to store',
            priority: 4
        },
        {
            title: 'Go to mall',
            priority: 3
        },
        {
            title: 'Get to work',
            priority: 5
        }
    ]);
    var addTaskView = new App.Views.AddTask({ collection: tasks });
    var tasksView = new App.Views.Tasks({ collection: tasks });
    $('div.tasks').append(tasksView.render().el);
})();

したがって、モデルの検証は正常に機能します...唯一のpbは、collection.addが新しく追加されたモデルを検証しないことです....検証を強制する方法はありますか?

ありがとう、レアーズ

4

2 に答える 2

2

細かいマニュアルから:

検証 model.validate(attributes, options)

[...] デフォルトでは、 validateは の前に呼び出されますが、が渡さsaveれる前に呼び出すこともできます。set{validate:true}

Collection#add呼び出したり、オプションsaveで呼び出したりしません。中に検証したい場合は、次のように言います。setvalidate: trueadd

collection.add(models, { validate: true });

それはvalidate:trueまでずっと下がりModel#setます。

単純化された例を簡単に見てみると、役立つ場合があります。

var M = Backbone.Model.extend({
    set: function() {
        console.log('setting...');
        Backbone.Model.prototype.set.apply(this, arguments);
    },
    validate: function() {
        console.log('validating...');
        return 'Never!';
    }
});
var C = Backbone.Collection.extend({
    model: M
});
var c = new C;
c.on('add', function() {
    console.log('Added: ', arguments);
});
c.on('invalid', function() {
    console.log('Error: ', arguments);
});

これを行うと(http://jsfiddle.net/ambiguous/7NqPg/):

c.add(
    { where: 'is', pancakes: 'house?' },
    { validate: true }
);

setが呼び出されvalidate: truevalidateが呼び出され、エラーが発生することがわかります。しかし、これを言うと(http://jsfiddle.net/ambiguous/7b2mn/):

c.add(
    { where: 'is', pancakes: 'house?' },
    {add: true, merge: false, remove: false} // Your options
);

なくsetても呼び出され、呼び出されずvalidate: true、モデルがコレクションに追加されることがわかります。validate


上記の動作は非常に強く暗示されていますが、明示的に指定されていないため、信頼したくない場合があります. Model#initialize言う:

モデルにある属性の初期値を渡すことができますset

setオプションについて明示的に言及していますvalidate。ただし、 がCollection#addオプションをモデル コンストラクsetターに送信したり、モデルのコンストラクターがオプションを に送信したりする保証はありませんset。したがって、本当に偏執狂的で将来の証拠になりたい場合は、この「オプションが最後までset」動作のクイックチェックをテストスイートに追加できます。それが変更された場合は、それについて知ることができ、修正することができます。

于 2013-06-23T20:03:33.210 に答える