2

我想确保在创建新模型时特定属性在集合中是唯一的,以便我最终可以将此属性用作永久链接。

我有一个列表集合和列表模型。(咖啡脚本)

class App.Models.List extends Backbone.Model
  defaults:
    name: "My New List"

class App.Collections.ListSet extends Backbone.Model
  model: App.Models.List

将新模型添加到 ListSet 时,如果已经存在具有该名称的模型,我想在名称属性的末尾添加一个自动递增的数字。例如My New List 1,如果模型与My New List.

我不希望它突兀并显示错误,而只是自动修复问题。我对添加递增整数背后的逻辑感到满意,但我需要说明在何处放置代码以进行更改。

4

2 回答 2

1

这可能对您有用:

App.Models.List = Backbone.Model.extend({
    initialize: function(attrs) {
        this.set(attrs);
        this.set({originalName: attrs.name});

        var count = yourCollection.reduce(function(count,model){
            return count + (model.get('originalName') === this.get('originalName') ? 1 : 0);
        },0,this);

        if(count > 0) {
            this.set({name: this.get('name') + ' ' + count});
        }
    }
});

这是一个演示:jsFiddle DEMO

这应该做的是每次初始化模型时,扫描您的集合以查看是否有任何其他模型具有相同originalName的 . 如果是这样,您将结果附加到名称属性。

=== 更新 ===

我现在意识到最好在将模型添加到集合时进行修改,以便将模型与集合分离。这是一个更新的代码片段:

App.Models.List = Backbone.Model.extend({
    initialize: function(attrs) {
        this.set({originalName: attrs.name});
    }
});

App.Collections.Lists = Backbone.Collection.extend({
    model: App.Models.List,
    initialize: function() {
        this.on('add',this.resolveNameConflict,this);
    },
    resolveNameConflict: function(model){
        var count = this.reduce(function(c,m){
            return c + (m.get('originalName') === model.get('originalName') ? 1 : 0);
        },0);
        if(count > 1) {
            model.set({name: model.get('originalName') + ' ' + (count-1)});
        }
    }
});

和一个演示:jsFiddle DEMO

于 2012-07-16T18:51:47.547 回答
0

更新:jackwander 的答案是一个更好的解决方案...... 不过,我将把它保留在这里,因为将我的幼稚解决方案与他的解决方案进行比较和对比很有趣。初学者程序员,你可以通过评估两者来学习一些东西。:-)


我会试一试。你可能会做这样的事情。基本上,我们添加一个 eventListener,每次您将模型添加到集合时都会进行名称检查。该nameTracking数组是一种名称对象的目录,具有唯一的名称片段和跟踪名称根的最后计数的计数器。对于我们的递增应用程序很有用。

ListSet = Backbone.Collection.extend({

    initialize: function() {
        this.nameTracking = [];
        this.on('add', this.pushModelName, this);
    },

    pushModelName: function(model, collection) {

        // First, look through current collection for a model with same name
        var duplicate = this.find(function(listModel) {
            return model.get('name') === listModel.get('name');
        });

        // If duplicate exists, we lookup the name and counter in the nameTracking array.
        if (duplicate) {

            var nameObj = _.find(this.nameTracking, function(nameObj) {
                return nameObj.name === model.get('name');
            });

            // We increment the counter so that our added model is appended with the
            // correct, "latest" increment/indicator
            nameObj.count = nameObj.count++;
            model.set('name', model.get('name') + '_' + nameObj.count);

        // Otherwise it doesn't exist so we push the name into our nameTracking array
        } else {    // Not a duplicate, new name

            var modelName = model.get('name');

            this.nameTracking.push({
                'name': modelName,
                'count': 0
            });

        }
    }
});

需要注意的是,这假设您要添加的模型是一个新模型,而不是已经具有集合中已经存在的模型的 id(不是克隆)。您还需要一些方法来更新nameTracking[]on集合初始化,或者fetch()因为这假设您从头开始。我不处理模型的删除和更新名称计数器的东西,但根据这个草图,如果你想要这种性质的东西,它应该不难实现。

于 2012-07-16T18:18:19.173 回答