BrainLikeADullPencil
BrainLikeADullPencil

Reputation: 11673

Ember Data not creating an id for new instances

I created a prototype of an Ember app using the Local Storage adapter.

I am now trying to convert the app to use the Ember Data REST adapter with a back-end store.

In the local storage version of the app, Ember generates an id for a new record prior to saving it (and also even if the record is never saved).

For example, in my local storage app, I can log the id in both places

var gecko = this.store.createRecord('gecko', {
    date: new Date(),
    type: "gecko",                                     
    });
  console.log(gecko.id, "gecko.id before save");
  gecko.save();
  console.log(gecko.id, "gecko.id");

By contrast, in the version of the app I'm making with the REST adapter for the back-end store, the id is not logged.

When I check the data Ember is sending to the server, the id is not included (probably because an id was never generated).

Here is the json that Ember is sending to my server

  gecko: { type: "alloc", date: "2015-05-30T13:28:27.539Z"}

I am assuming that I am supposed to save the id that Ember generates on my server (which would of course allow it to retrieve the record by id provide my server implements that).

Question: why is there no id being generated?

this is the code

    App = Ember.Application.create();

    App.Router.map(function() {
      this.route("gecko", { path: "/" });

    });
    App.ApplicationAdapter = DS.RESTAdapter.extend({
    //haven't actually any created any code for this part yet
    });
    App.ApplicationStore = DS.Store.extend({
      adapter: App.ApplicationAdapter.create() 
    });
    App.Gecko = DS.Model.extend({
      type: DS.attr('string'),
      date: DS.attr('date')
    })
    App.GeckoRoute = Ember.Route.extend({

      model: function() {
       //currently does nothing. originally I tried to do `return this.store.find('gecko') but since there are no records yet on the backend, it's returning null which leads to an error which Array cannot map over
      },
    });
App.GeckoController = Ember.Controller.extend({

  actions: {
       createGeckoButtonClicked: function(){

            var gecko = this.store.createRecord('gecko', {
                date: new Date(),
                type: "gecko",                                     
            });
            console.log(gecko.id, "gecko.id before save"); //null
            gecko.save();
            console.log(gecko.id, "gecko.id"); //null
       }


  }

Note—I'm not sure if it's relevant, but I feel like I'm in a chicken/egg situation with the route because I can't return any entries before I have created them.

So therefore, I'm trying to setup the Ember app to be able to POST an entry to the server, then I will implement the route to retrieve it using return this.store.find('gecko').

Upvotes: 2

Views: 1850

Answers (2)

afroglasses
afroglasses

Reputation: 63

When you use the RESTAdapter and save a model, ember-data expects for a valid payload that includes a unique id generated by your backend.

var gecko = this.store.createRecord('gecko', {
    date: new Date(),
    type: "gecko",                                     
});

/*
   Here ember-data expects a payload like this:
        gecko: {id: 1, date: "", type: "gecko"}
   The id is generated by your backend
*/
gecko.save().then(function(gecko){
    console.log(gecko.get('id'))
})

Upvotes: 4

Kingpin2k
Kingpin2k

Reputation: 47367

Ember Data doesn't create ids, there isn't anything to stop it from generating non-unique ids. It isn't the source of truth when it comes to gecko records, your database is, so id generation belongs to the db. This is where POST vs PUT comes into play. I want to POST a new gecko record to /api/geckos or I want to PUT gecko record 123 into its place at /api/geckos/123.

If there are no entries in the database you should still be returning a valid response:

{
    geckos: []
}

And two other quick things, you should be using getters/setters for property fetching and setting.

var gecko = this.store.createRecord('gecko', {
  date: new Date(),
  type: "gecko",                                     
});
console.log(gecko.get('id'), "gecko.id before save");
var promise = gecko.save();

And save is an asynchronous process that returns a promise which you can wait to avoid race conditions.

promise.then(function(geckoRecord){
   // geckoRecord and geck are the same here, but it's good to know
   // it resolves the record
   console.log(gecko.get('id'), "gecko.id after save");
   console.log(geckoRecord.get('id'), "gecko.id after save");
});

Upvotes: 1

Related Questions