Ember js handles API endpoints with embedded resource URLs

Part of my API is configured as follows:

/v1/place/:place_uuid - get a place

/v1/place/:place_uuid/cart - get the shopping cart object associated with this place

My routes are configured correctly (see below), but the API requests made by Ember do not match my own.

 App.Router.map(function() { this.resource('place', { path: '/:place_uuid' }, function() { this.resource('category', { path: '/:category_uuid' }, function() { this.resource('product', { path: '/:product_uuid' }); }); this.resource('cart', { path: '/cart' }); }); }); 

When I load /:place_uuid in the browser, I see the correct API request to /v1/place/:place_uuid . The route displays the returned object.

When I load /:place_uuid/cart in the browser, I see the same as above, as well as the second API request for /v1/carts . All of this is great, except for the URL /v1/carts . I need it to be /v1/place/:place_uuid/cart

I tried using buildURL with a custom adapter for the Cart model. But no luck. I do not have access to place_uuid anywhere below, so I cannot enter it.

 cartAdapter = App.Adapter.extend({ buildURL: function(record, suffix) { console.log(record); // just a string. var url = [this.url]; url.push('places'); url.push(place_uuid); // if only I had access to place_uuid I could inject it here url.push('cart'); return url.join("/"); } }); App.Store.registerAdapter('App.Cart', cartAdapter); 

It would be great if I could use my source API endpoint, I believe the other option is to change the endpoint to /v1/carts?place_uuid=:place_uuid (which Ember seems to prefer, but a bit complicated since I am not working on a backend).

Any advice is appreciated.

+4
source share
3 answers

Ember does not yet support sub-REST URLs. There is an open problem for this feature that you can control.

+4
source

Here is my approach:

Download your DS.Store as follows:

 import DS from 'ember-data'; export default { name: 'patches', initialize: function() { // +++ Nested routes + DS.Store.reopen({ __nestedAdapter__: null, nest: function(type) { this.set('__nestedType__', this.adapterFor(type)); return this; }, withResources: function(resources) { this.get('__nestedType__').set('nestedResources', resources); this.set('__nestedType__', null); return this; } }); } }; 

Add this to your adapter:

 import DS from 'ember-data'; export default DS.RESTAdapter.extend({ nestedResources: {}, buildURL: function(type, id, record) { var resources = this.nestedResources; var parts = [this.get('host')]; for(var key in resources) { if (resources.hasOwnProperty(key)) { var resource = resources[key]; parts.push( Ember.Inflector.inflector.pluralize(key) ); if(isNaN(resource)) { parts.push(resource.get('id')); } else { parts.push(resource) } } } parts.push( Ember.Inflector.inflector.pluralize(type), id ); this.set('nestedResources', {}); console.log(parts.join('/')); return parts.join('/'); } }); 

Use expressive syntax:

 that.store.nest('user').withResources({comment: comment}).find('user') 

It can be cut for sure, but I like it.

+1
source

Shameless plug :)

I wrote https://github.com/amiel/ember-data-url-templates to deal with this situation. It works with newer versions of ember data. With it, you can do something like this:

 App.CartAdapter = App.ApplicationAdapter.extend({ queryUrlTemplate: "/v1/place/{placeId}/cart", urlSegments: { placeId(type, id, snapshot, query) { return query.placeId; } } }); // in the route this.store.query('cart', { placeId: placeId }); 

Hope this helps :)

+1
source

Source: https://habr.com/ru/post/1479285/


All Articles