【问题标题】:How to "fork" a model in Ember Data如何在 Ember Data 中“分叉”模型
【发布时间】:2013-11-06 16:02:50
【问题描述】:

我不确定这是否是表达我的要求的正确方式。但是“fork”这个词出现在 Ember Data github 页面的路线图中。这是 EPF 的杀手级功能。我想知道我是否可以在 Ember Data 中做到这一点。

当我们有一个编辑页面并绑定一个模型时,fork 功能很有用。当我们编辑信息时,我不希望更改模型属性,因为如果模型属性也显示在其他位置,它们将自动更改。那不是我想要的。

一个示例是页面左侧的列表和页面右侧的特定模型的编辑表单。当我在文本字段中修改角色名称时,由于数据绑定,左侧的角色名称发生了变化。

EPF 通过“分叉”现有模型并将其设置在子会话中来解决此问题。 EPF 中的 session 与 Ember Data 中的 store 类似。当您修改分叉模型时,它不会影响主会话中的模型。分叉模型更新后可以合并回主会话,主会话中对应的模型也会更新。

我认为 Ember Data 中的解决方案是创建一个不同的存储并将模型复制到该存储。但这有点复杂。有没有人有更好的解决方案?我在stackoverflow和ember讨论论坛上搜索,没有找到答案。

【问题讨论】:

  • 我想我明白你在说什么。我过去做过类似的事情,但我的解决方案并不是那么好。基本上,我将Model.toJSON 调用到一个新的Em.Object 实例中,并将视图绑定到这个新实例,然后当我完成编辑(或任何操作)时,我会序列化回存储中的实际模型(仅更新模型中与新对象不同的属性)。您是否尝试过类似的方法?
  • 实际上,目前这与我在我的站点中所做的类似。但我选择将Em.Object 封装为模型。我复制模型以绑定到编辑表单。但是这个解决方案对 Ember Data 来说并不好,因为当你想更新一个模型时,你应该给这个模型设置属性并调用save,在这种情况下它还会修改所有其他绑定相同模型的 UI,所以我不能只使用复制的Em.Object 来做到这一点。
  • 这只是一个想法......当我这样做时,我在调用 store save 之前添加了一个额外的步骤,所以我在控制器中有一个动作来从模型中提取数据和/或每次我需要在绑定到视图的对象中读取或写入时序列化回来。之后我已经转移到事务,所以在我保存之前它们不会传播更改。我有一段时间没有时间接触这个,或者任何与 Ember 相关的东西,就像我说的那样,这只是一个想法
  • 啊,你想克隆编辑吗?是的,我使用类似的东西,并且有一个功能可以遍历并替换原始数据。所有人都起床时很笨拙。也许您应该在 ember.js 存储库中请求它?我很想在 ember 中看到这个功能!
  • @Slevin 这不是他(@MilkyWayJoe)所说的。他说他使用了一个简单的 Em.Object,然后在用户完成编辑后他用它来更新模型对象。这是一种“破解”的方式,即编辑模型对象会立即更新,而不是像 darkbaby123 所希望的那样“分叉”。

标签: ember.js ember-data


【解决方案1】:

我不确定在 Ember 中是否有 standard 或 common 方法来执行此操作,但我已经编写了一个 Mixin,我可以将它放在我的路由上给出模型的一些基本“缓冲”:

App.BufferedRouteMixin = Ember.Mixin.create({
    setupController: function(controller, model) {
        this.setBufferFromModel(controller, model);
        this._super(controller, model);
    },
    setBufferFromModel: function(controller, model) {
        var buffer = {};
        controller.set('model', model);
        model.eachAttribute(function(name, meta) {
            buffer[name] = model.get(name);
        });

        controller.set('buffer', buffer);
    },
    setModelFromBuffer: function() {
        var model = this.get('model'),
            buffer = this.get('buffer');

        model.eachAttribute(function(name, meta) {
            if (buffer[name]) {
                model.set(name, buffer[name]);
            }
        });
    }
});

将其添加到我的编辑路线后,我可以在我的 save 操作中调用 setModelFromBuffer。在我的模板中,我可以使用 {{#with buffer}} 助手。

【讨论】:

  • 很丑不是吗。考虑到当前的情况,这是一个很好的解决方案。我认为这对我们所有人来说真的很有用,并在这个问题上表示支持github.com/emberjs/data/issues/1901 似乎已经有很多了。
【解决方案2】:

我认为最简单的解决方案是拥有一个模仿模型结构的Ember.Object。进入编辑模式时,将模型中的属性复制到Ember.Object,然后让它们在那里更新,直到用户单击“保存”或您希望合并更改的任何操作。我做的一件重要的事情是将 mixin Ember.Copyable 添加到我的对象中。下面是我自己解决这个问题的一些代码。

注意:: 这段代码是为了防止模型在提交之前被创建,所以我的不是编辑,而是创建新的。

App.SomeModel = DS.Model.extend({
  user: DS.belongsTo('user'),
  home: DS.belongsTo('home'),

  cost: DS.attr('number'),
  title: DS.attr('string'),
  description: DS.attr('string'),
  category: DS.attr('number'),
  categoryName: function () {
    return Roomy.enums.TransactionCategories[this.get('category')]
  }.property('category'),
  date: DS.attr('date', {
       defaultValue: function() { return new Date(); }
  }),
  fuzzyDate: function () {
    return moment(this.get('date')).fromNow();
  }.property('date'),
  split: DS.attr('boolean'),
  contributors: DS.attr('array'),
  points: DS.attr('number')
});

App.SomeModelNew = Ember.Object.extend(Ember.Copyable, {
  user: null,
  home: null,
  cost: null,
  title: null,
  description: null,
  category: null,
  date: new Date(),
  split: false,
  contributors: [],
  points: null,
  copy: function () {
    return this.getProperties('cost', 'title', 'description', 'category', 'date', 'split', 'contributors', 'user', 'home');
}
});

然后为了保存这个模型,我做了这样的事情。
注意:: 由于关系,我必须使用带有 User 和 Home 的代码,简单地复制 User 和 Home 的 json 形式不会持久化关系并为模型提供它在数据库中所需的 ID。

控制器代码如下:

//Before this function is called, all the inputs in the form have been filled in and the instance now has values for all the fields that were defined for it
saveTxn: function (txn) {
    // txn is the App.SomeModelNew instance
    copy = this.store.createRecord('transaction', txn); // this returns the App.SomeModelNew.copy() object
    copy.set('user', txn.get('user')); // OVerwrite user for relationship
    copy.set('home', txn.get('home')); // Overwrite home for relationship
    return copy.save();
}

我希望这会有所帮助。

【讨论】:

  • 所以你提倡有效地复制整个模型。这简直太臭了。
  • 我想对于我的应用程序来说,由于我的对象非常小,开销并不大。不过我很想看到一个更正确的方法来解决这个问题,所以我会继续关注这个问题
  • 很公平,我猜。一般来说,作为开发人员,我们可以忍受少量重复(上帝,例如,我要输入多少次“函数”这个词?PEH!)但是我们可以删除重复,我们绝对应该尝试。我认为这种偶然的复杂性最终决定了以后是否能够添加功能,这有点令人难过。 :(
  • 是的,我想另一种选择可能是扩展DS.Model,并为其赋予属性stagedChanges 和函数addToStage、commitStage。您不想立即显示的所有属性都添加到 stagedChanges 对象中,该对象将按照 setProperties 方法所需的确切方式进行格式化。完成更改后,您调用commitStage,这将应用所有属性更改,然后您可以立即将模型保存到您的代码中
  • 你应该看看我在回购中创建/链接到的关于“分叉”的链接,我想。有人给出了一个很好的例子,说明了您想要的可能解决方案。
猜你喜欢
  • 2013-11-22
  • 2012-08-23
  • 2023-03-07
  • 2014-04-28
  • 2013-11-21
  • 1970-01-01
  • 1970-01-01
  • 2023-03-23
  • 1970-01-01
相关资源
最近更新 更多