Find by different property

Is there a way to find a record not by id. but via slug property. Still I want to keep ids in store as primary key.

if my route is “/post/:slug” then I want to fetch record by slug from API. Also I’d like to search the store if the record with the same slug already exists.

Can you advice something on implementation? I think that’s pretty common usage (with slugs), but unfortunately I got no ideas how to get this done right.

Yes. You simply need to add serilalize to your route, rename your path to the slug, then read it from model in the route

In your router

@route 'post', path: '/post/:slug'

In your routes

App.PostRoute = Ember.Route.extend(
  model: (params) ->
    App.Post.find params.slug

  setupController: (controller, model) ->
    controller.set 'content', model

  serialize: (model) ->
    slug: model.get 'slug'
)

(this refers to ember-data <= 0.14, it may have changed with 1.0)

It seems as though the issue where doing this results in duplicate records still hasn’t been resolved.

Unless your backend always returns the slug as a reference then you could end up with one record with the numeric ID and one with the slug ID.

App.Post.find(params.slug) will add a model with the slug as the ID to the store (even if the numeric ID is returned from the server)

App.Post.find(id) will add a model with the numeric ID to the store

There are workarounds for it. I’m using the following in my user route:

App.Router.map ->
  @resource 'user', { path: '/user/:user_id' }

App.UserRoute = Ember.Route.extend
  serialize: (model, params) ->
    if model && model.get
      { user_id: model.get('username') }

  model: (params) ->
    users = App.User.find({id: params.user_id})
    users.one 'didLoad', ->
      users.resolve(users.get('firstObject'))
    return users

Note that this will perform a query to /users not /users/:id, hence the need to grab the first result.

If anyone has a more elegant solution to this I’d be glad to hear it!

@lookingsideways Thanks, I had similar thoughts with fetching item by query and resolving it into one record. Unfortunately something didn’t work for me (maybe I misuse promises of 1.0beta). Your solution can be improved if a map for “slug” => “id” is created, so models can be cached by their slug.

Anyway, I decided to follow KISS and set the slug as the primary key for my records. That simplified code. In my project I have opportunity to get non-unique slugs, depending on a project. Thus, I will clean up store on switching a project.