Find by different property


#1

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.


#2

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'
)

#3

(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!


#4

@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.