【问题标题】:ember-data: Updating a record with a many-to-many relationship?ember-data:更新具有多对多关系的记录?
【发布时间】:2014-01-01 22:56:28
【问题描述】:

我有一个 File 和一个 Tag 模型,它们是多对多的关系:

App.File = DS.Model.extend
  name: DS.attr('string')
  tags: DS.hasMany('tag')

App.Tag = DS.Model.extend
  name: DS.attr('string')
  files: DS.hasMany('file')

我正在读取通过 Rails 后端生成的 JSON 数据,到目前为止一切正常。我正在尝试在我的 Ember 路由中编写一个 tagFile 函数,该函数使用特定标签标记文件。这在 ember 端可以正常工作,但它当然不会持续存在,而且我不知道如何将正确的 HTTP 请求发送到 Rails 后端。所以我有

App.FilesRoute = Ember.Route.extend
  ...
  actions:
    tagFile: (file, tag) ->
      file.get('tags').pushObject(tag)
      tag.get('files').pushObject(file)
      # file.save() ? or something similar?

我试过file.save(),它发送一个PUT请求,但是在Rails中发送的params哈希根本不包括Tag记录。我在 ember-data 内部的 updateRecord() 方法中设置了一个断点,并在通过 AJAX 发送之前检查了 data 变量,并且该变量也不包括 Tag 记录。

发送 HTTP 请求(PUT 或其他)的正确方法是什么,我可以将我的子记录传递到 params 哈希中?有没有办法使用 ember-data 方法传递任意数据?我可以编写自己的 AJAX 调用,但似乎我没有利用 ember-data。有什么见解吗?

使用:Ruby 2/Rails 4 后端,Ember 1.3.0-beta.1+canary.48513b24,Ember-data 1.0.0-beta.4+canary.c15b8f80

【问题讨论】:

    标签: ember.js ruby-on-rails-4 many-to-many ember-data


    【解决方案1】:
     file.get('tags').pushObject(tag);
     tag.save();
     file.save();
    

    Dual hasMany 会将它们连接在一起http://emberjs.jsbin.com/OxIDiVU/94/edit

    如果您想为其中一种类型创建自定义序列化程序以包含另一种类型。这是 ED 稍作修改的一个

    App.FileSerializer = DS.RESTSerializer.extend({
       serialize: function(record, options) {
        var json = {};
    
        if (options && options.includeId) {
          var id = get(record, 'id');
    
          if (id) {
            json[get(this, 'primaryKey')] = get(record, 'id');
          }
        }
    
        record.eachAttribute(function(key, attribute) {
          this.serializeAttribute(record, json, key, attribute);
        }, this);
    
         var tags = [];
        record.eachRelationship(function(key, relationship) {
          if (relationship.kind === 'belongsTo') {
            this.serializeBelongsTo(record, json, relationship);
          } else if (relationship.kind === 'hasMany') {
            record.get(relationship.key).forEach(function(tag){
              tags.push(tag.toJSON());
            });
            //this.serializeHasMany(record, json, relationship);
          }
        }, this);
    
        json.tags = tags;
    
        return json;
      }
    });
    

    http://emberjs.jsbin.com/OxIDiVU/95/edit

    或者更具体的序列化器

    App.FileSerializer = DS.RESTSerializer.extend({
       serialize: function(record, options) {
        var json = {}, 
            tags=[];
    
        json.id = record.get('id'); 
        json.name = record.get('name');
    
        record.get('tags').forEach(function(tag){
          var tagJson = {};
          tagJson.id = tag.get('id');
          tagJson.name = tag.get('name');
          tags.push(tagJson);
        });
    
        json.tags = tags;
    
        return json;
      }
    });
    

    http://emberjs.jsbin.com/OxIDiVU/96/edit

    【讨论】:

    • 感谢您的及时回复!对于您的第一个解决方案,涉及 2 次保存,我的代码似乎发送了两个 PUT 请求,一个发送到 file#update,一个发送到 tag#update。我在某个地方犯了错误吗?我希望它向file#update 发送一个PUT 请求,并提供tag 记录。此外,重写序列化程序会影响我的代码的其余部分吗,这与使用侧面加载的 JSON 的 ActiveRecordSerializer 一样工作?
    • 知道了,我会使用第三个示例,并删除标签上的保存。序列化仅用于放置/发布。你会看到我是怎么做的FileSerializer 它只会用于文件记录。这是ActiveModelSerializeremberjs.jsbin.com/OxIDiVU/97/edit
    猜你喜欢
    • 1970-01-01
    • 2013-03-15
    • 2014-12-10
    • 1970-01-01
    • 1970-01-01
    • 2015-10-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多