How to save many-to-many relations


I have 2 models with a many-to-many relations:

  • Shop
  • Event

Being on templates/events/index.hbs page that displays the list of events, how is possible to assign an event to a shop (I have the instance of the current shop everywhere in the application via a service current-shop) ?

My first idea was to create an end-point on the backend side (`Rails’)

POST /shops/:shop_id/events/:id(.:format) v1/shop_events#handle_event

The difficulty I have on Ember side is how to call the above route from controllers/events/index.js controller ?

I tried to do as follows:

handleEvent(event) {
  let event ='event', 1);
  let shop ='shop', 1);

but, of course Ember tried to hit PATCH http://localhost:3000/shops/:shop_id.

I’m using ember-data-url-templates and override adapters when needed. How to solve that without modifying the existing shop adapter ?

Thank you.


Personally, I like exposing the join model as a resource, and just managing those.


I created a separate model for ShopEvent:

import DS from 'ember-data';

export default DS.Model.extend({
  shop: DS.belongsTo(),
  event: DS.belongsTo()

Then I created its adapter to manage the end point:


import ApplicationAdapter from './application';
import UrlTemplates from "ember-data-url-templates";

export default ApplicationAdapter.extend(UrlTemplates, {
  urlTemplate: '{+host}/shops/{shopId}/events',
  createRecordUrlTemplate: '{+host}/shops/{shopId}/events/{eventId}',

  urlSegments: {
    shopId: function(type, id, snapshot, query) {
      if (query && query.shop_id) {
        return query.shop_id;
      return snapshot.belongsTo('shop', { id: true });

    eventId: function(type, id, snapshot, query) {
      if (query && query.event_id) {
        return query.event_id;
      return snapshot.belongsTo('event', { id: true });

And finally in the controller action I save a ShopEvent resources s follows:

actions: {
    async handleEvent(event) {
      let published = event.get('published');
      let flashText = published ? 'flash.event.activated' : 'flash.event.deactivated';
      let shop = this.get('');
      let eventId = event.get('id');
      let shopEvent ='shopEvent', {
        shop: shop,
        event:'event', eventId),

      await this.transitionToRoute('country-events');


@NullVoxPopuli It seems to work for creating a ShopEvent instance but fails for deletion :frowning: Here is what I’m trying to do in country-events/index.js controller (the template displays country events and I have to activate/deactivate an event for a shop):

async handleEvent(event) {
      let activated = this.activatedByShop(event);
      let flashText = activatedByShop ? 'flash.event.deactivated' : 'flash.event.activated';
      let eventToHandle ='event', event.get('id'));
      let shop = this.currentShop.get('shop');

      let shopEvent ='shopEvent', {
        shop: shop,
        event: eventToHandle
      if (activated) {        
      } else {


  activatedByShop(event) {
    let shopEventsIds = this.get('').mapBy('id');
    return shopEventsIds.includes(event.get('id'));

The problem is that delete end-point is never hit :frowning:. Any idea ? Thank you.