Using Ember CLI and working with Ember Data fixtures

April 29th, 2015

Ember CLI is pretty much the defacto way to work with Ember these days. It makes creating new elements of an application extremely easy. Lately I have been working on using Ember Data so I wanted to do a little write-up on how to use Ember Data fixtures. Fixtures are a great way to start working on your application before you have an API to work with. It is also a great way to determine what your API’s data should look like.

Set up

Lets assume you have a basic Ember application set up. And you are running Ember CLI. If you are not 100% sure how to do so check out my post Working with Ember Data, Node, Express and Mongodb to get an idea, the first portion will get you started.

The Model

The first thing we need to so is create our model using Ember Data. Using the Ember CLI we can generate a new model by typing:


ember generate model note

Inside our note model, now located at app/models/note.js, lets define some attributes. In this case we are just going to have three properties, a title, an author and the content. Using DS.attr() we can define the type the attributes will be.


import DS from 'ember-data';

export default DS.Model.extend({
    title: DS.attr('string'),
    author: DS.attr('string'),
    content: DS.attr('string')
});

Notice that once we use Ember CLI to create a model it will default to setting our file to be export default DS.Model.... In order for us to create a FIXTURE we need to change that to be something like this.


import DS from 'ember-data';

var Note = DS.Model.extend({
    title: DS.attr('string'),
    author: DS.attr('string'),
    content: DS.attr('string')
});

export default Note;

Now when can use the Note variable to create our fixture data. In order to add fixture data to our model we need to use the reopenClass() method.


import DS from 'ember-data';

var Note = DS.Model.extend({
    title: DS.attr('string'),
    author: DS.attr('string'),
    content: DS.attr('string')
});


Note.reopenClass({
    FIXTURES: [
        
    ]
});

export default Note;

Inside the FIXTURES array we can now add our objects that will represent our fixture data.


Note.reopenClass({
    FIXTURES: [
        {
            id: 1,
            title: "Using Ember CLI to create a Fixture Adapter.",
            author: "Ryan Christiani",
            content: "Lorem ipsum dolor sit amet, consectetur adipisicing elit. Laudantium aspernatur quam qui commodi beatae placeat ducimus aliquam veritatis ullam sed! Sit assumenda aspernatur sunt harum accusamus, repellat labore! Repellendus, corporis!"
        },
        {
            id: 2,
            title: "Ember is lots of fun",
            author: "Ryan Christiani",
            content: "Lorem ipsum dolor sit amet, consectetur adipisicing elit. Laudantium aspernatur quam qui commodi beatae placeat ducimus aliquam veritatis ullam sed! Sit assumenda aspernatur sunt harum accusamus, repellat labore! Repellendus, corporis!"
        },
        {
            id: 3,
            title: "Ember, Node, Express and You!",
            author: "Ryan Christiani",
            content: "Lorem ipsum dolor sit amet, consectetur adipisicing elit. Laudantium aspernatur quam qui commodi beatae placeat ducimus aliquam veritatis ullam sed! Sit assumenda aspernatur sunt harum accusamus, repellat labore! Repellendus, corporis!"
        }
    ]
});

export default Note;

The Fixture Adapter

Now we have to create our adapter. To do so lets create a new application adapter.


ember generate adapter application

This will create a new DS.RESTAdapter.extend in the folder app/adapters/application.js. To set up a fixture, it is as simple as changing DS.RESTAdapter.extend to DS.FixtureAdapter.extend.

Testing that it works.

In order to test that it works we need to create and application router.


ember generate router application


import Ember from 'ember';

export default Ember.Route.extend({
    model: function() {
        return this.store.find('note');
    }
});

Now in our template we can use our model and output the data!


{{#each model as |item|}}
    {{item.content}}
{{/each}}

And that is it! Now you can start working on your application and work with data, even if you don’t an api to connect with! I hope that helps some people!

  • Serabe

    I like creating an `app/fixtures` folder where all my fixtures are. Then, from each model I just `import FIXTURES from ‘project/fixtures/pluralized-name-of-model’;` and I’ll reopen the class with the configuration object `{FIXTURES}`. This lets me keep my fixtures in a different place in case they need to grow.

    • Ryan Christiani

      Oh, that is a really good idea! Thanks!

    • http://kyleshevlin.com/ Kyle Shevlin

      Hey, I thought this was a good idea, but I’m getting an error trying to implement it. My apologies in advance for the long comment to follow.

      Created an `app/fixtures` directory. Added a file in this directory that was a plural of my model, in this case `songs.js`. I copied and pasted the FIXTURES array I originally had in my `song.js` model (and think this may be where my mistake is). Contents of `fixtures/songs.js`:
      “`
      FIXTURES: [
      // objects here, not showing for brevity.
      ]
      “`
      Then in my `song.js` model, I have:
      “`
      import DS from ’ember-data’;
      import FIXTURES from ‘mymusic/fixtures/songs’;

      export default DS.Model.extend({
      title: DS.attr(‘string’),
      lyrics: DS.attr(‘string’),
      file_url: DS.attr(‘string’)
      }).reopenClass({FIXTURES});
      “`
      The error I am getting is: `Cannot read property ‘default’ of undefined` and can see this in the sources:
      “`
      define(‘mymusic/models/song’, [‘exports’, ’ember-data’, ‘mymusic/fixtures/songs’], function (exports, DS, FIXTURES) {
      ‘use strict’;

      exports[‘default’] = DS[‘default’].Model.extend({
      title: DS[‘default’].attr(‘string’),
      lyrics: DS[‘default’].attr(‘string’),
      file_url: DS[‘default’].attr(‘string’)
      }).reopenClass({ FIXTURES: FIXTURES[‘default’] });
      });
      “`
      Do I need a different setup in my `fixtures/songs.js` file to accomplish this separation?

  • Tayhobbs

    The #each helper block syntax you are using in the example is deprecated. The new syntax is
    {{#each model as |item|}}
    {{item.content}}
    {{/each}}

    • Ryan Christiani

      Thanks, updated. Oddly Ember CLI and the inspector did not give me deprecation notices!?

      • Tayhobbs

        Maybe I jumped the gun and that is marked to be deprecated in 1.12, which is due for release any day now.

  • seangore

    Why not just use API stubs? If you have a model, you can stub out the response in a much more intuitive way, if you put the JSON file in /api. After all, we’re all unit testing anyway, right?

    • Ryan Christiani

      Yup, sure could just do that.
      But I wanted to show how one can also build it this way.

  • Tyler Wendlandt

    well written Ryan. Excellent resource for those wanting to test out ember apps without apis.

  • Troy S

    For some reason this does not work for me no matter what I do. I followed this to the “T” and when I look at ember inspector, it says I have zero models loaded.

    Ember Inspector 1.8.0
    Ember 1.11.1
    Ember Data 1.0.0-beta.16.1
    jQuery 1.11.3

    Also, why does the documentation say you only need to add App.ApplicationAdapter = DS.FixtureAdapter.extend();?

  • Daniel Alonso Nuñez Labarca

    hi all 🙂 i was reading and fixtures for ember 2.0.0 are deprecate.. can you give a example like thist with restadapter o oder model of data ember ?

  • Matthew

    When I do ember generate router application, I get: Unknown blueprint: router

    version: 1.13.8
    node: 4.1.2
    npm: 2.13.4
    os: darwin x64

    • Ryan Christiani

      That is because router is no a blueprint, you want to use route.

  • Rilwanrabo

    ember generate router application // no blueprint route, it should be route instead