ember get

Now for number 4 in the Ember Data and REST server saga. Don't miss the others:

Installing Ember Data

Because Ember Data is still under very active development, I recommend downloading the latest passing Canary build here.

After downloading the ember-data.js file movit it into the static/js/libs directory so it can be with it's friends Handlebars, jQuery, and of course Ember.js itself. Next, edit index.html and add the following after the script tag for Ember.js, but before the app.js tag:

    <script src="js/libs/ember-data.js"></script>

Refresh your browser, or start the server and go to http://localhost:5000, and make sure there are not problems with loading the new Ember Data file. If you don't see any errors in the browser's JavaScript Console, congradulations you have successfully installed Ember Data. Party!

Setting Up Ember Data

It's time to adjust the static/js/app.js file to use Ember Data instead of a static jQuery $.ajax().

First, setup a Model object for our DVDs. Add the following to app.js after the App.Router.map section:

  var attr = DS.attr;

App.Dvd = DS.Model.extend({
  title: attr('string'),
  created_by: attr('string'),
  created_at: attr('date'),
  rating: attr('number'),
  file_url: attr('string'),
});

Change the IndexRoute to use the new App.Dvd model instead of straight jQuery ajax:

  App.IndexRoute = Ember.Route.extend({
   model: function() {
     return this.store.find('dvd');
   }
});

If you refresh your browser now, will will get a 404 error because we have only setup our /dvds route to respond to the POST HTTP method and we just sent it a GET method.

So let's modify our super cool server.py file.

Update The Server

First, add a GET method to the /dvds route:

  @app.route('/dvds', methods=['POST', 'GET'])

Next, add an elif to check for the GET and call a new function find_all():

  elif (request.method == 'GET'):
  return json.dumps({"dvds": find_all(Dvd)})

Below the dvds() function add the the find_all() and jsonable() functions:

  def jsonable(sql_obj, query_res):
  """
  Return a list of dictionaries from query results since SQLAlchemy
  query results can't be serialized into JSON evidently.
  """
  cols = sql_obj.__table__.columns
  col_keys = [col.key for col in cols]

  obj_list = []
  for obj in query_res:
    obj_dict = {}
    for key, value in obj.__dict__.iteritems():
      if (key in col_keys):
        if (type(value) == datetime.datetime):
          value = value.strftime("%Y-%m-%d %H:%M:%S")
        obj_dict[key] = value
    obj_list.append(obj_dict)

  return obj_list


def find_all(sql_obj):
  """
  Return a list of all records in the table.
  """
  q = session.query(sql_obj)
  return jsonable(sql_obj, q)

The find_all() function performs an SQL query through the SQLAlchemy ORM we setup earlier, and jsonable() creates a nice Python list of dictionaries from the results. One sort of drawback with SQLAlchemy is that there isn't a built in method to create a JSON object from query results. Maybe that will be added in the future, but in the meantime the jsonable() helper should work just fine.

Back in the browser at http://localhost:5000 do a refresh and you should see an unordered list of strange output similar to:

  <App.Dvd:ember411:1>

The reason for this strange output is because the the Handlebars template needs to be updated for our new Ember Data objects. Edit the index.html file changing {{each}} loop to:

      {{#each}}
    <li>
    {{id}}
    <br/>
    {{title}}
    <br/>
    {{created_at}}
    <br/>
    <br/>
    </li>
    {{/each}}

Alrighty, we now have a cool REST GET method returning data from a SQL table. Woooo!