creating a record with Ember.js & Ember-data & Rails and handling list of records

We use a variation of solution 3 in several places on our app. IMHO it's the cleanest of the 3 as you don't have to worry about setup/teardown on the server side This is how we implement it:

App.PostsController = Ember.ArrayController.extend({
  sortProperties: ['id'],
  sortAscending: true,
  filteredContent: (function() {
    return this.get('content').filter(function(item, index) {
      return !(item.get('isDirty'));
    });
  }).property('content.@each')
});

Then in your Posts template you loop through controller.filteredContent instead of controller.content.

For solution 1, there are many possibilities. You could define the following event:

  createPost: function() {
    var post,
      _this = this;
    post = App.Post.createRecord({});
    post.one('didCreate', function() {
      return Ember.run.next(_this, function() {
        return this.transitionTo("posts.edit", post);
      });
    });
    return post.get("store").commit();
  }

It creates the post then sets up a promise that will be executed once "didCreate" fires on the post. This promise transitions to the post's route only after it has come back from the server, so it will have the correct ID.


Indeed, very nice write up. Thx for that.

Doesn't your filteredContent have to use the isNew state i.o. isDirty, otherwise the Post that is being edited will not be visible. In either case, the filteredContent property does not work in my case. I also noticed that, since I use an image as part of every element, all images will be refreshed when filteredContent is changed. This means that I see a request for every image.

I use a slightly different approach. I loop through the content and decide whether or not to display the Post in the template:

# posts.handlebars
<ul class='posts'>
  {{#each controller}}
    {{#unless isNew}}
      <li>
        <h3>{{#linkTo post this}}{{title}}{{/linkTo}}</h3>
        <img {{bindAttr src="imageUrl"}}/>
        <a {{action deletePost}} class="delete-post tiny button">Delete</a>
      </li>
    {{/unless}}
  {{/each}}
</ul>

This will only show the Post object after it is saved. The url in the H3-tag also contain the id of the newly created object i.o. posts/null.

One other thing I noticed in your question: instead of passing default values to createRecord, you can use the defaultValues property on the model itself:

So, instead of:

# App.PostsNewRoute
var post = transaction.createRecord(App.Post, {
            title: 'default placeholder title',
            body: 'default placeholder body'
       });

you can do this:

# App.Post
App.Post = DS.Model.extend({
  title: DS.attr('string', {
    defaultValue: "default placeholder title"
  }),
  body: DS.attr('string', {
    defaultValue: "default placeholder body"
  })
});

# App.PostsNewRoute
var post = transaction.createRecord(App.Post);