Multiple data stores and model namespacing (different models with same name)

Greetings,

Most similar questions are about having the same model connect to different backend apis.

What I want to achieve is to have two totally different models with different properties but with the same name connect to different apis. I tried different approaches, but I assume the only real way (and logical) is to have multiple data stores. At the same time, I’ve found no documentation on multiple stores and even found information that says multiple stores should not be used in Ember (ember.js - Can I specify a Store on a Ember js model? - Stack Overflow). This was back in the days when name spacing was done differently.

I have created an addon with just the models, adapters, serializers, and a new store service called “core-store”. Each entity extends a “core” adapter and serializer so that the addon doesn’t use the main project’s “application” adapter and serializer.

The addon’s “core-store” service:

import DS from 'ember-data';

export default DS.Store.extend({
    adapter: 'core'
});

The main project’s route that queries the “core-store”

import Route from '@ember/routing/route';
import { inject as service } from '@ember/service';

export default Route.extend({
    coreStore: service(),

    model(params) {
        let workplace = this.get('coreStore').findRecord('workplace', params.master_id);
        return workplace;
    }
});

The main project contains several models that have the same name as the addon’s models. The workplace model has relationships to these. When it builds the model instances, it chooses to use the main project’s instead of the addon’s.

I can give more info if need be. I’ve tried many approaches, but I have yet to try the ember addon for multiple stores: https://github.com/jonesetc/ember-cli-multi-store-service. Going to give it a try while I wait for replies.

Please do let me know what the best approach here is. I’m surprised there isn’t much info

When it builds the model instances, it chooses to use the main project’s instead of the addon’s.

This is Ember’s normal behavior. Anything defined in your application will override something of the same name defined in an addon. Otherwise if there are two totally different modules with the same name it is impossible to correctly disambiguate them.

What I want to achieve is to have two totally different models with different properties but with the same name connect to different apis.

Could you describe your use case here a bit more and why you want them to have the same name? I have a hunch you may be able to come up with something less complex than multiple stores but it really depends. You could always avoid using Ember Data for one/both of these models too.

dknutsen, thanks for the reply.

The last thing I want to do is avoid using Ember Data. That would be skipping out on a lot of powerful features.

I would rather choose the option to call the models different names like “model” and “core-model” which is a solution that works but is not elegant at all, but better than skipping out on Ember Data.

And yes, that is the default, but is there a way to override the default and specify which namespace you want. I was hoping that by using a different store with a custom adapter specified, it would somehow magically know to choose the models that have the specified adapter.

The use case: I have a core set of models that are shared across several ember apps (engines). Then there are also the models that are very specific to the app. These models are very different and have different backends.

Lets say I have a model called “master” in the addon

export default DS.Model.extend({
    phone: DS.attr('string'),
    name: DS.attr('string'),
    lastname: DS.attr('string'),
    email: DS.attr('string'),
    sex: DS.attr('string'),
    isOnline: DS.attr('boolean'),
    city: DS.belongsTo('city'),
    workplaces: DS.hasMany('workplace')
});

and a “master” model in the main project:

export default DS.Model.extend({
    name: DS.attr('string'),
    role: DS.attr('string'),
    rating: DS.attr('number'),
    img: DS.attr('string'),
    position: DS.attr('number')
});

Yeah I’d go with different model names. Even if it’s not exactly what you want it’s probably going to be a lot simpler and result in fewer headaches vs multiple stores or other workarounds. I suppose it would be nice if an engine’s ember data stuff was all separate but that would probably create a lot more complexity in other ways. Based on the way things work IMHO any unique collection of fields (e.g. a model) should have a unique name.

1 Like

I’ll have to go with the different model names approach unfortunately. It’s far from an elegant solution. It just seems crazy that you can’t have multiple stores with their own set of models and namespaces. I’m still hoping someone will come in an say that I’ve missed something and is indeed doable.

From what I recall, SproutCore had this feature. Did Ember really remove this powerful feature? There are also other advantages of having several stores such as branching and nesting them instead of committing changes to one global store.

What is this even for then? https://emberjs.com/api/ember-data/release/classes/DS.Store

//Define your application's store like this:

//app/services/store.js
import DS from 'ember-data';

export default DS.Store.extend({
});

I feel like I may be doing something wrong.

Another idea that I had was to have the addon with the models be an engine as well so that it can have its completely own store that doesn’t get added into the main project (from what I understand) as with an addon and access it through the engines dependancies system. http://ember-engines.com/guide/services

I mean I don’t see why you can’t have multiple stores. You could certainly extend the store as many times as you wanted to and inject those new stores wherever you wished. Might require a lot of customization work but it’s worth a shot if that’s really the way you want to go. I’ve never tried it and maybe there are those who have who can weigh in more.

What’s wrong with namespacing the models? Why not call one foo/master and the other bar/master? It seems like they are actually different things, so they shouldn’t be referred to by the same name if they are not the same thing.

Using different stores is off the beaten path, so you may find things don’t work. I’m pretty sure you won’t be able to have relationships that cross the store boundary, for example, and would expect things like the ember inspector to not handle it well. It’s definitely not the usual thing to do.

4 Likes