2
votes

I have a File and a Tag model, which are in a many-to-many relationship:

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')

I'm reading the data as JSON generated via Rails backend, and so far everything works fine. I'm trying to write a tagFile function in my Ember route that tags a file with a specific tag. This works fine on the ember side but of course it doesn't persist, and I can't figure out how to send the proper HTTP request to the Rails backend. So I have

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

I've tried file.save(), which sends a PUT request, but the sent params hash in Rails does not include the Tag record at all. I set a breakpoint in the updateRecord() method inside ember-data, and examined the data variable before it gets sent via AJAX, and this variable does not include the Tag record either.

What is the correct way to send an HTTP request (PUT or otherwise) where I can pass along my child record into the params hash? Is there a way to pass arbitrary data using ember-data methods? I could write my own AJAX call but then it seems like I'm not taking advantage of ember-data. Any insights?

Using: Ruby 2/Rails 4 backend, Ember 1.3.0-beta.1+canary.48513b24, Ember-data 1.0.0-beta.4+canary.c15b8f80

1

1 Answers

1
votes
 file.get('tags').pushObject(tag);
 tag.save();
 file.save();

Dual hasMany will connect them together http://emberjs.jsbin.com/OxIDiVU/94/edit

If you want to create a custom serializer for one of the types to include the other. Here's a slightly modified one from 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

Or a more specific serializer

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