4

我正在使用 ember.js 和 couchdb 实现一个应用程序。我选择 ember-resource 作为数据库访问层,因为它很好地支持嵌套的 JSON 文档。

由于 couchdb 使用属性 _rev 在每个文档中进行乐观锁定,因此在将数据保存到 couchdb 后,必须在我的应用程序中更新此属性。

我实现这一点的想法是在保存到数据库后立即重新加载数据,并将新的 _rev 与文档的其余部分一起返回。

这是我的代码:

// Since we use CouchDB, we have to make sure that we invalidate and re-fetch
// every document right after saving it. CouchDB uses an optimistic locking
// scheme based on the attribute "_rev" in the documents, so we reload it in
// order to have the correct _rev value.
didSave:     function() {
    this._super.apply(this, arguments);
    this.forceReload();
},

// reload resource after save is done, expire to make reload really do something
forceReload: function() {
    this.expire();  // Everything OK up to this location
    Ember.run.next(this, function() {
        this.fetch()  // Sub-Document is reset here, and *not* refetched!
            .fail(function(error) {
                App.displayError(error);
            })
            .done(function() {
                App.log("App.Resource.forceReload fetch done, got revision " + self.get('_rev'));
            });
    });
}

这适用于大多数情况,但如果我有一个嵌套模型,则在执行获取之前,子模型将替换为旧版本的数据!

有趣的是,正确的(更新的)数据存储在数据库中,而错误的(旧的)数据在获取后存储在内存模型中,尽管 _rev 属性是正确的(以及主对象的所有属性)。

这是我的对象定义的一部分:

App.TaskDefinition = App.Resource.define({

url: App.dbPrefix + 'courseware',

schema: {
    id:          String,
    _rev:        String,
    type:        String,
    name:       String,
    comment:    String,
    task:        {
        type:   'App.Task',
        nested: true
    }
}
});

App.Task = App.Resource.define({

schema: {
    id: String,
    title:       String,
    description: String,

    startImmediate: Boolean,
    holdOnComment: Boolean,
    ..... // other attributes and sub-objects
}
});

问题可能出在哪里?

非常感谢您的任何建议!

亲切的问候,托马斯

4

1 回答 1

5

我找到了一个更好的解决方案,可以从数据库中取回新修订版,而无需在每次保存后重新加载数据。

如果使用更新选项save调用ember-resource,则来自 db 的响应将合并到资源对象中。couchdb 对保存请求的回答类似于

{"ok":true,"id":"mydocument-123","rev":"10-5f3cb46df301143a966251148f88663d"}

所以我只是将_rev我的对象的属性设置rev为数据库中的值。

我的应用程序特定资源类作为所有 couchdb 对象的超类如下:

App.Resource = Ember.Resource.extend({

    save: function(options) {
        options = options || {};
        options.update = true; // sets id and rev after saving in ember-resource; rev is copied to _rev in didSave callback!
        this.set('rev', undefined);
        return this._super(options);
    },

    // we get the new revision in the "rev" attribute of the response from the save-request.
    // since we set options.update to true, we get this value in the attribute "rev", which we simply copy to "_rev"
    didSave:     function() {
        this._super.apply(this, arguments);
        this.set('_rev', this.get('rev'));
    }

    .... // other properties and functions
});

资源定义如下:

App.TaskExecution = App.Resource.define({

    ....

    schema: {

        id:   String,
        _rev: String,
        rev:  String,
        type: String,
        .....  // other attributes
    }

});

到目前为止工作得很好......

于 2012-06-19T21:13:51.727 回答