Chad
Chad

Reputation: 18396

Ember, Ember Data and MongoDB's _id

I've seen this question talked about but I'm still having issues with manhandling Mongo's _id into id. I'm using mongoose as my ORM and while it has virtuals I can't seem to get it to work properly. Below is what I have in my mongoose model.

Attempt To Fix From The Backend

mongoose = require 'mongoose'
Schema = mongoose.Schema
ObjectId = Schema.ObjectId

ApartmentSchema = new Schema
  body: String
  date: { type: Date, default: Date.now }
  deleted: {type: Boolean, default: false}
  saved: {type: Boolean, default: false}
  visited: {type: Boolean, default: false}
  email: String
  phoneNumber: String
  href: String

ApartmentSchema.virtual('id').get -> return @_id

module.exports = mongoose.model 'Apartment', ApartmentSchema

When I create a new instance of this model in express I can do a look up like apt.id and get the id back but when I send the response down to the client, I just have _id and not id.

The second solution I tried was to create a computed property for id but for whatever reason ember does not like this. There are 2 problems here. Ember does not respect a computed property called id or at least not anymore. This is what my ember-data model looks like.

Attempt To Fix It From The Frontend

App.Apartment = DS.Model.extend({
  body: DS.attr('string'),
  date: DS.attr('date'),
  deleted: DS.attr('boolean'),
  saved: DS.attr('boolean'),
  visited: DS.attr('boolean'),
  email: DS.attr('string'),
  phone: DS.attr('string'),
  _id: DS.attr('string'),
  id : function () {
    return this.get('_id')
  }.property('_id')
});

In my template below, nothing renders for the id.

{{#each apartment in controller}}
    <li>{{apartment.body}} | {{apartment.date}} | {{apartment.href}} {{apartment.id}}</a>  {{#linkTo 'apartment' apartment }} View {{/linkTo}} </li>
{{/each}}

The linkTo helpers work but the url has null where the id should be. This results in breaking of the backbutton and loading the data multiple times. Below is my router for some context.

App.Router.map(function(){
  this.resource('apartments', function (){
    this.resource('apartment', { path: ':apartment_id' } );
  });
});

Changing the name of my computed id property to something like foo and then changing my router to path: ':apartment_foo' results in urls that have the object reference in the url eg: #/apartments/<App.Apartment:ember357:null>.

It's stuff like this that kind of erks me about ember. Any help would be appreciated.

Upvotes: 8

Views: 4368

Answers (5)

tbjers
tbjers

Reputation: 572

As of Ember 2.0.0 the proper way to normalize Mongo IDs is to use the extractId in the serializer. Here's an example for RESTSerializer running against a Rails/Grape API:

import DS from 'ember-data';

export default DS.RESTSerializer.extend({
  isNewSerializerAPI: true,
  extractId: function (modelClass, resourceHash) {
    return resourceHash.id.$oid;
  }
});

Note that you have to set isNewSerializerAPI to true for this to work.

For your need, you could try to change to resourceHash._id.$id or whatever else works for you. If you're unsure, try console.log(resourceHash) to inspect the data.

Upvotes: 0

Josh Hardy
Josh Hardy

Reputation: 361

Since the migration to Ember-CLI, this process has changed slightly. You now want to do this:

  1. From the Ember-CLI project command line:

    ember g serializer application
    
  2. Make your newly created serializer look like this:

    import DS from 'ember-data';
    
    export default DS.RESTSerializer.extend({
      primaryKey: '_id'
    });
    

Upvotes: 2

owerme
owerme

Reputation: 270

I had the same problem as Chris with an id looking something like this:

"_id":{"$oid":"52772aa44f6c6c5dd0000000"}

Adding the $oid part to claptimes' solution worked for me.

App.ApplicationSerializer = DS.RESTSerializer.extend({
  primaryKey: "_id.$oid"
});

Upvotes: 5

claptimes
claptimes

Reputation: 1717

As of Ember Data - Version: v1.0.0-beta.2, I was able to do the following:

App.ApplicationSerializer = DS.RESTSerializer.extend({
  primaryKey: "_id"
});

I'm pretty new to Ember, so this might not be the best method, but it worked!

Upvotes: 7

Chad
Chad

Reputation: 18396

As of Ember 1.0.0-rc 1 and Ember Data revision 11, this seems to be the best way to resolve this.

App.Adapter = DS.RESTAdapter.extend({
  serializer: DS.RESTSerializer.extend({
    primaryKey: function(type){
      return '_id';
    }
  })
});

App.Store = DS.Store.extend({
  revision: 11,
  adapter: 'App.Adapter'
});

Upvotes: 9

Related Questions