Adapter updates in beta-16.1?

Hey friends,

Hoping someone can help spot the issue I’m having or maybe point me in the right direction. In my app, we use a repository pattern to alter the namespace for certain requests. An example would be when we want to make a request to https://apiserver.com/v1/users/:id/workspaces. By default my adapter namespace is set to v1. Prior to sending the request with ember-data, I append users/:id to the namespace of the adapter, then send the request with store.find('workspace'). Up until ember-data 1.0.0-beta.15, this approach has worked swimmingly. I find that after upgrading to beta-16.1 that the namespace alteration isn’t picked up by the buildURL method, or I suppose it occurs after buildURL is run.

  • Is it possible that this has anything to do with the Snapshot API?
  • With the new injection method in initializers, could that have anything to do with it? I’m not doing any container.lookup in the initializer, so this may be a non-issue.
// repositories/workspace.js
  appendResources: function () {
    this.clearAppendedResources();

    var adapterNamespace = this.get('adapter.namespace'), // We're injecting the adapter into repositories
        prefix = [adapterNamespace];

    if (arguments.length) {
      // For each argument, lookup the related id. Push both to the namespace
      for (var i=0; i < arguments.length; i++) {
        prefix.push(arguments[i]);
      }
      this.set('adapter.namespace', prefix.join('/'));
    }
  },

  // The method that ties it all together
  getWorkspacesByUser: function (user_id, params) {
    var self = this;

    if (params === undefined) {
      params = {};
    }

    this.appendResources('users', user_id); // We alter the namespace here
    this.setupIncludes(); // We append some ?include=yadayada params here

    // Make the request! Should be to /v1/users/:id/workspaces
    return this.store.find('workspace', params).finally(function () {
      // Clean up all the things
      self.clearIncludes();
      self.clearAppendedResources();
    });
  }

Here’s how we’re building the URL in the adapter for reference:

  // adapters/workspace.js
  buildURL: function(type, id, snapshot) {
    var url = this._super(type, id, snapshot);
    return this.buildIncludeURL(url);
  },

  buildIncludeURL: function (url) {
    if (this.includes.length) {
      url += '?include=' + this.includes.join(',');
    }
    return url;
  }

Yu say you’re injecting the adapter into repositories?

The adapters and serialisers have changed in that they are no longer singleton. Each instance of a store maintains its own serialiser and adapter instances… This might be part of your problem - your altering an injected adapter while requests are using a different adapter (one your store has created)

1 Like

That’s interesting and the most logical conclusion. So when requests are made the store, a new instance of an adapter and serializer is instantiated for each request?

Nope - the store maintains a single instance. It uses that one instance for each request.

When calling store.adapterFor('workspace') you will always get back the same instance.

1 Like

Ah. Sorry for my lack of knowledge about ED core. I’m assuming this means adapters are no longer registered with the container and bound directly to the model instance?

Is there a specific place/source file I should look at so I can grok this without asking you a bo-jillion questions?

Adapters are still registered against the container - they initially come from the container - when the store first creates them…

You could look at this pull request which is the one that implemented this particular change - but don’t mind me - if you have any more questions (and I’m capable of answering) I’m happy to help (:

So the benefit of having adapters and serializers not registered as singletons is to prevent collisions between apps using multiple stores or stores registered other than store:main? Neat. So another question…if I want to affect some properties on the adapter or serializer prior to making a request, would it be best to lookup the specific adapter instance with store.adapterFor(‘type’)?

p.s. Great work on that PR. You da man.

The whole thing started because the EmbeddedRecordMixin used the store property which was always the store:main - so there was no way to get embedded records in a store other than store:main.

store.adapterFor('type') is the way to go - yep.

1 Like