Ember Data, Custom Ajax


#1

Hi,

99% of my app uses restful Ember data. But a few actions we want to keep as member routes (for server side reasons).

I’ve looked over other threads, like this, but still not sure ideal way to keep it as Ember-like as possible.

Simple example

ContactRequest model

var ContactRequest = DS.Model.extend({
  sender: DS.belongsTo('profile')
});

ContactRequest.reopen({
  accept: function () {
    var self = this;
    return new Em.RSVP.Promise(function (resolve, reject) {
      Em.$.post('api/v1/contact_requests/' + self.get('id') + '/accept').done(function () {
        resolve();
      }).fail(function () {
        reject();
      });
    });
  }
});

export default ContactRequest;

controller

export default Em.ObjectController.extend({
  actions: {
    accept: function () {
      this.get('model').accept().then(function () {
        // handle success
      }, function () {
        // handle fail
      });
    }
  }
});

Then I can also loadMany into the store, etc.

This feels clean to me, so I’m fine with it. But is it the best place? Should it instead go in the adapter?

But my biggest question is this goes outside of application adapter. I want to inherit headers for my API, and preferably the host / namespace (api/v1 etc) that I have set up in application adapter.

Any ideas on how to do this the cleanest way possible?


#2

I do something very similar in my app for data about the model that is ephemeral. Like your intuition told you, I put the AJAX logic on the model’s adapter so that it has access to ajax(), and anything that is inherited from the application adapter (host, namespace, anything custom like headers).

App.ContactAdapter = App.ApplicationAdapter.extend({
  accept: function(contactId) {
    var urlParts = [ this.urlPrefix(), 'contact_requests', id, 'accept' ];
    return this.ajax(urlParts.join('/'), 'POST').then(function(response) {
      // extract data from the response
      return response.stuff;
    });
});

App.ContactModel = DS.Model.extend({
  accept: function() {
    var adapter = this.store.adapterFor(this.constructor);
    return adapter.accept(this.get('id'));
  }
});

This of course is my own approach, but I consider it fairly clean.


#3

Hey thanks for response, I like that approach a lot.