Ember CLI model namespacing


#1

I have an ember-cli application using ember-data that consumes multiple API endpoints (using different adapters and serializers). How do I handle Two endpoints having a model entity of the same name effectively? If endpointA has a model named “posts” with a certain structure and endpointB also returns an entity named “posts” with an entirely different structure, how can I segregate my models and refer to them appropriately?

Ideally, the models directory would allow for sub-folders to define namespace. As in:

/models /endpointsA/posts.coffee /endpointsB/posts.coffee

I would then refer to my findAll for posts as “endpoints-a.posts”. Is there an existing way to have this functionality that I am glaring over? Thanks!

Brian


#2

Since you already fine with making a requests per endpoint, then you can use model specific adapters.

Imagine if each endpoint was mapped like /models/endpointsA/posts.coffee => /models/postsOne.coffee

You would need an adapter per endpoint you would need to hit.

var PostOneAdapter = DS.RESTAdapter.extend({
   host: ENDPOINT_A
});
export default PostOneAdapter;

Then you would request them as usual.

store.findAll('postsOne')
...
store.findAll('postsN')

#3

More asking for help than providing an answer but…how do you configured your ember-cli project in order to use two different endpoints?

Don’t you need to create two different stores?


#4

Ember-Data expects that there will be [model specific adapters][1]. If it cannot find the adapter for the model the resolver will fall back to using the application adapter. You can create multiple adapters that all connect to a separate endpoint and use the same store for all the models.

If you need to know how the resolver is looking for your adapters, turn on the logging for it.

ENV.APP.LOG_RESOLVER = true;

Then you can inspect the console to see at what path is it looking the adapter. [1]: http://emberjs.com/guides/models/customizing-adapters/


#5

Thank you all for the feedback. I have still found it strange and a little bit interesting to come up with a solution where-in i may have multiple rest endpoint URL path signatures to obtain the same model. While in the interim I am working with to modify the API, I’m still confused on the best way to have potentially multiple OR dynamic URL data adapters for a SINGLE MODEL. Why duplicate a model more than once?

b


#6

I have the same issue, but I’m hitting the same server for the same model with different paths/namespaces. I can’t find an effective way to update the namespace to use different paths. The ‘namespace’ property of the RESTAdapater seems to be consulted before any of the events fire that are available for me to hook into. There is the ‘url’ property on the Router that seems to be kept up to date, but it feels a bit shaky to use it. Does anyone know how to reliably set the namespace/path prior to the request being made?


#7

A rather ‘unclean’ way of setting the namespace per route basis could be done using Adapter.prototype.namespace = ‘newNamespace’;

Example:

// ExampleRoute
import Ember from 'ember';
import ApplicationAdapter from '../adapters/application'; // Import adapter

export default Ember.Route.extend({
  model: function() {
    // This overrides the adapters namespace
    ApplicationAdapter.prototype.namespace = 'api/v0/content'; 

    // YOUR CODE i.e.
    return this.store.find('example', 1)
  }
});

Note that this workaround will only change the adapter namespace for that particular route, and only code following the namespace change. I’m having the same issue as OP and @terryroe, I’ll update my post when I’ve found a cleaner solution.


#8

I have another workaround that I’m using for this issue that you might find interesting. What I did was first add a namespace export to each model definition.

export const namesapce = 'content';

Then I overrode the pathForType function in my application adapter to dynamically import that variable like so:

pathForType(type) {
	const module_name = Ember.String.dasherize(type)
    const namespace = dynamicImport('MY-EMBER-APP/models/' + module_name,'namespace');

	const url_type = Ember.String.pluralize(module_name)

    return namespace + '/' + url_type;

},

Here’s the dynamic Import function

export default function dynamicImport(moduleName, objName) {
    var module_obj = Ember.RSVP.Promise.resolve(window.require(moduleName));
    return module_obj._result[objName];
}