I have 2 models with a many-to-many relations:
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 = this.store.peekRecord('event', 1);
let shop = this.store.peekRecord('shop', 1);
shop.get('events').pushObject(event);
shop.save();
}
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:
#adapters/shop-event.js
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('currentShop.shop');
let eventId = event.get('id');
let shopEvent = this.store.createRecord('shopEvent', {
shop: shop,
event: this.store.peekRecord('event', eventId),
});
await shopEvent.save();
this.get('flashMessages').success(this.get('i18n').t(flashText));
await this.transitionToRoute('country-events');
}
}
@NullVoxPopuli It seems to work for creating a ShopEvent instance but fails for deletion
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 = this.store.peekRecord('event', event.get('id'));
let shop = this.currentShop.get('shop');
let shopEvent = this.store.createRecord('shopEvent', {
shop: shop,
event: eventToHandle
});
if (activated) {
shop.get('events').removeObject(eventToHandle);
shopEvent.deleteRecord();
} else {
shop.get('events').addObject(eventToHandle);
}
await shopEvent.save();
this.get('flashMessages').success(this.get('i18n').t(flashText));
this.send('refreshModel');
this.transitionToRoute('country-events');
}
},
activatedByShop(event) {
let shopEventsIds = this.get('currentShop.shop.events').mapBy('id');
return shopEventsIds.includes(event.get('id'));
}
The problem is that delete
end-point is never hit . Any idea ? Thank you.
1 Like