# How Ember knows which URL to hit in the backend?

**URL:** <https://discuss.emberjs.com/t/how-ember-knows-which-url-to-hit-in-the-backend/14428>\
**Category:** Ember Data\
**Created:** [March 22, 2018, 9:32am UTC](https://discuss.emberjs.com/t/how-ember-knows-which-url-to-hit-in-the-backend/14428 "2018-03-22T09:32:43Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![belgoros](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.emberjs.com/belgoros/32/16101_2.png) [@belgoros](https://discuss.emberjs.com/u/belgoros)\
**Post date:** [March 22, 2018, 9:32am UTC](https://discuss.emberjs.com/t/how-ember-knows-which-url-to-hit-in-the-backend/14428/1 "2018-03-22T09:32:43Z")

</div>

I can’t figure out what is the convention rule in the when querring in `model` hook in a route handler. How Ember knows which URL to hit in the following situation:

Here is my router definition:

```auto
#router.js
Router.map(function() {
 ...
  this.route('languages', { path: '/shops/:shop_id/languages'});
});

```

Here the link definition in a template:

```auto
#application.hbs
{{#link-to 'languages' currentUser.user.shop.id class="nav-link"}}...{{/link-to}}

```

Here the route handler:

```auto
#languages.js

export default Route.extend(AuthenticatedRouteMixin, {
  model(params) {
    return this.store.query('language', { shop: params.shop_id })
  }
});

```

I hoped that Ember to hit `shops/:shop_id/languages` URL, but it did `/languages?shop=6449` instead. Can somebody explain me the role of `language` String in `this.store.query('language', { shop: params.shop_id })`, - I belived that Ember would just deserialize `language` model (defined in `models/language.js`). Thank you.

---

<div class="post-metadata">

**Author:** ![belgoros](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.emberjs.com/belgoros/32/16101_2.png) [@belgoros](https://discuss.emberjs.com/u/belgoros)\
**Post date:** [March 22, 2018, 2:09pm UTC](https://discuss.emberjs.com/t/how-ember-knows-which-url-to-hit-in-the-backend/14428/2 "2018-03-22T14:09:19Z")

</div>

Is there an easier solution other than to implement a proper adapter and override `query` method defined in [JSONAPIAdapter](https://emberjs.com/api/ember-data/3.0/classes/DS.JSONAPIAdapter/methods/query?anchor=query) or or `urlForQuery` from [BuildURLMixin](https://emberjs.com/api/ember-data/3.0/classes/DS.BuildURLMixin)? Looks like I’ll have to override all the main URLs to create/edit/update a shop language because they use a different Ajax call (get, put, delete, etc.).

---

<div class="post-metadata">

**Author:** ![beddu](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.emberjs.com/beddu/32/16464_2.png) [@beddu](https://discuss.emberjs.com/u/beddu)\
**Post date:** [March 22, 2018, 3:43pm UTC](https://discuss.emberjs.com/t/how-ember-knows-which-url-to-hit-in-the-backend/14428/3 "2018-03-22T15:43:14Z")

</div>

Hi @belgoros,

I think you are making a little confusion, if I did not misunderstood your point, I will try to make it clear in the simplest way:

The router route’s path is used to specify an URL for the `{{link-to}}` helper, but it does have nothing to share with Ember Data.

If your backend implements `json:api` all you need to do is to implement the method `DS.JSONAPIAdapter.urlForQuery` as described [here](https://emberjs.com/api/ember-data/release/classes/DS.JSONAPIAdapter).

If your backend does not implement `json:api` you have, unfortunately, to handle all the communication yourself, that might be done by implementing an adapter yourself or to write it in bare javascript inside an external module and import it in your ember application.

I hope I did not misunderstand your question.

---

<div class="post-metadata">

**Author:** ![larryh](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.emberjs.com/larryh/32/16498_2.png) [@larryh](https://discuss.emberjs.com/u/larryh)\
**Post date:** [March 22, 2018, 3:49pm UTC](https://discuss.emberjs.com/t/how-ember-knows-which-url-to-hit-in-the-backend/14428/4 "2018-03-22T15:49:29Z")

</div>

Hi,

This was the source for a lot of confusion for me at first, mostly because I came from a Rails world where something like `/shops/3/languages` meant something to me w.r.t. the back end.

Since then I’ve come to realize that when you see a url like the one above in your browser’s address bar that you should view it as just a serialization of the app’s state, i.e. how to go about setting up models and templates in the browser’s window, as opposed to what is going to get sent to the server.

Something like this: `this.store.query('comments', {post: params.post_id})` will result in what you saw above being sent to the server: `GET api/comments?post=3`, while something like `this.store.findRecord('comment', params.comment_id)` will result in `GET api/comments/2`.

The key thing to remember is that `this.store.query(~~~)` will always result in attaching query params to the url, while `this.store.findRecord(~~~)` will spit out what you were hoping for above, i.e. the params being inserted into the meat of the url.

I hope that answered your question.

---

<div class="post-metadata">

**Author:** ![belgoros](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.emberjs.com/belgoros/32/16101_2.png) [@belgoros](https://discuss.emberjs.com/u/belgoros)\
**Post date:** [March 22, 2018, 4:59pm UTC](https://discuss.emberjs.com/t/how-ember-knows-which-url-to-hit-in-the-backend/14428/5 "2018-03-22T16:59:22Z")

</div>

Thank you, guys, for your responses ! The solution I came to is the following:

- I created a `shop-language.js` adapter:

```auto
export default ApplicationAdapter.extend({
  urlForQuery (query, modelName) {
    return `/shops/${query.shopId}/languages`;
  }
});

```

Then call `query` in `languages.js` route handler model hook:

```auto
export default Route.extend(AuthenticatedRouteMixin, {
  model(params) {
    return this.store.query('shop-language', { shopId: params.shopId});
  }
});

```

And the shop languages route is defined in `router`like that:

```auto
Router.map(function() {
  this.route('languages', { path: '/:shopId/languages'});
...
});

```

It seems to work, any other remarks are welcome !

Thank you!

---

<div class="post-metadata">

**Author:** ![dknutsen](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.emberjs.com/dknutsen/32/16471_2.png) [@dknutsen](https://discuss.emberjs.com/u/dknutsen)\
**Post date:** [March 22, 2018, 5:16pm UTC](https://discuss.emberjs.com/t/how-ember-knows-which-url-to-hit-in-the-backend/14428/6 "2018-03-22T17:16:02Z")

</div>

One other way to handle “nested” models like this is, if your shop model has a hasMany(‘language’) relationship, you can use “links” either in your backend response or add them in your shop serializer. Then when you fetch shops.get(‘languages’) it will fetch the languages async from the url that you specify in related “links”.

Essentially in JSON API links are a way of providing related data or paginated data URLs as part of your payload (instead of sideloading the data or providing ids). So while the normal resource structure is assumed to be “flat”, you can use links to fetch “nested” data like this.

---

<div class="post-metadata">

**Author:** ![belgoros](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.emberjs.com/belgoros/32/16101_2.png) [@belgoros](https://discuss.emberjs.com/u/belgoros)\
**Post date:** [March 23, 2018, 8:14am UTC](https://discuss.emberjs.com/t/how-ember-knows-which-url-to-hit-in-the-backend/14428/7 "2018-03-23T08:14:51Z")

</div>

@dknutsen, Thank you for your response. Is there any example or docs on how to use the above solution ? Thank you. I’m using Rails as back-end API.

---

<div class="post-metadata">

**Author:** ![belgoros](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.emberjs.com/belgoros/32/16101_2.png) [@belgoros](https://discuss.emberjs.com/u/belgoros)\
**Post date:** [March 23, 2018, 8:19am UTC](https://discuss.emberjs.com/t/how-ember-knows-which-url-to-hit-in-the-backend/14428/8 "2018-03-23T08:19:58Z")

</div>

One more question: I see that I have XHR request hit as follows:

```auto
http://localhost:4200/shops/613/languages?shopId=613

```

Is it possible to remove the query param in the end `?shopId=613`, - it is already present in the URL followed by `languages`.

---

<div class="post-metadata">

**Author:** ![dknutsen](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.emberjs.com/dknutsen/32/16471_2.png) [@dknutsen](https://discuss.emberjs.com/u/dknutsen)\
**Post date:** [March 23, 2018, 3:52pm UTC](https://discuss.emberjs.com/t/how-ember-knows-which-url-to-hit-in-the-backend/14428/9 "2018-03-23T15:52:42Z")

</div>

@belgoros again this requires having a hasMany(‘languages’) relationship on the shops model, and if you’re using JSON API the specifics might be a little different (try looking at the JSON API spec) because we’re using the Rest Adapter/Rest Serializer, but this is what we do:

In our users serializer for example, we link the “nested” accounts like so:

```auto
// serializers/user.js
...
  normalize: function(typeClass, hash, prop){
    // add an 'accounts' link to support our 'hasMany'
    hash.links = {
      accounts: `/users/${hash.id}/accounts`,
    };
    return this._super(typeClass, hash);
  },
...

```

Then whenever we have a user model and want to fetch the accounts for it we can simply say `user.get('accounts')` and it fetches them from that URL

---

<div class="post-metadata">

**Author:** ![belgoros](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.emberjs.com/belgoros/32/16101_2.png) [@belgoros](https://discuss.emberjs.com/u/belgoros)\
**Post date:** [April 5, 2018, 4:06pm UTC](https://discuss.emberjs.com/t/how-ember-knows-which-url-to-hit-in-the-backend/14428/10 "2018-04-05T16:06:32Z")

</div>

Should I include the accounts collection when returning a User from the backend or Ember will fetch the User accounts using the provided URL: ``/users/${hash.id}/accounts` ?

In my case I have relations defined both in Rails and Ember like a Shop has\_many Languages.

When getting shop languages like that:

```auto
#shop_serializer.js

export default DS.JSONAPISerializer.extend({
  normalize: function(typeClass, hash, prop){
    hash.links = {
      shopLanguages: `/shops/${hash.id}/languages`,
    };
    return this._super(typeClass, hash, prop);
  },
});

```

in the route handler:

```auto
# routes/shops/shop-languages.js
import Route from '@ember/routing/route';

export default Route.extend({
   model(params) {
    let shops = this.modelFor('shops');
    let shop = shops.findBy('id', params.shop_id);
    console.log('shops: ' + shops);
    console.log('shop: ' + shop);
    console.log(shop.get('shopLanguages'));
    return shop.get('shopLanguages');
  }
});

```

I get the following in the console:

```auto
XHR finished loading: GET "http://localhost:4200/shops"
shops: <DS.RecordArray:ember276>
shop: <draft-api-ember@model:shop::ember347:7>

```

but the url ``/shops/${hash.id}/languages` has never been hit. I checked the value of shops array and shop - all of them seem to be correct.

---

<div class="post-metadata">

**Author:** ![belgoros](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.emberjs.com/belgoros/32/16101_2.png) [@belgoros](https://discuss.emberjs.com/u/belgoros)\
**Post date:** [April 8, 2018, 8:14am UTC](https://discuss.emberjs.com/t/how-ember-knows-which-url-to-hit-in-the-backend/14428/11 "2018-04-08T08:14:36Z")

</div>

The baskend is using Rails API with [active\_model\_serializers](https://github.com/rails-api/active_model_serializers) gem, the response it is sending is 100% compatible json-api.
