5

Let's say I have a Rails app with the following layout (simplified this a bit from my actual project):

User
    has many Notes

Category
    has many Notes

Note
    belongs to User
    belongs to Category

Notes can either be obtained at:

/users/:user_id/notes.json
/categories/:category_id/notes.json

but not:

/notes.json

There are too many Notes across the whole system to send down in one request - the only viable way is to send only the necessary Notes (i.e. Notes that belong to either the User or Category the user is trying to view).

What would my best way of implementing this with Ember Data be?

1 Answers1

5

I would say simple:

Ember models

App.User = DS.Model.extend({
  name: DS.attr('string'),
  notes: DS.hasMany('App.Note')
});

App.Category = DS.Model.extend({
  name: DS.attr('string'),
  notes: DS.hasMany('App.Note')
});

App.Note = DS.Model.extend({
  text: DS.attr('string'),
  user: DS.belongsTo('App.User'),
  category: DS.belongsTo('App.Category'),
});

Rails controllers

class UsersController < ApplicationController
  def index
    render json: current_user.users.all, status: :ok
  end

  def show
    render json: current_user.users.find(params[:id]), status: :ok
  end
end

class CategoriesController < ApplicationController
  def index
    render json: current_user.categories.all, status: :ok
  end

  def show
    render json: current_user.categories.find(params[:id]), status: :ok
  end
end

class NotesController < ApplicationController
  def index
    render json: current_user.categories.notes.all, status: :ok
    # or
    #render json: current_user.users.notes.all, status: :ok
  end

  def show
    render json: current_user.categories.notes.find(params[:id]), status: :ok
    # or
    #render json: current_user.users.notes.find(params[:id]), status: :ok
  end
end

Be careful: these controllers are a simplified version (index may filter according to requested ids, ...). You can have a look at How to get parentRecord id with ember data for further discussion.

Active Model Serializers

class ApplicationSerializer < ActiveModel::Serializer
  embed :ids, include: true
end

class UserSerializer < ApplicationSerializer
  attributes :id, :name
  has_many :notes
end

class CategorySerializer < ApplicationSerializer
  attributes :id, :name
  has_many :notes
end

class NoteSerializer < ApplicationSerializer
  attributes :id, :text, :user_id, :category_id
end

We include sideload data here, but you could avoid it, setting the include parameter to false in ApplicationSerializer.


The users, categories & notes will be received & cached by ember-data as they come, and missing items will be requested as needed.

Community
  • 1
  • 1
Mike Aski
  • 9,180
  • 4
  • 46
  • 63
  • Will Ember Data automatically request using the appropriate URL (/users/:user_id/notes.json or /categories/:category_id/notes.json) just based on the association? – user1539664 Jul 20 '12 at 05:55
  • No, it will use `/notes`, but your controller will ensure join, traversing relationship starting from the (categories|users), so the dataset will be limited to only usefull instances. – Mike Aski Jul 20 '12 at 06:03
  • So there's no way allowing access to the notes from both the Category and the User objects? – Yossi Shasho Aug 17 '12 at 13:53