<?xml version="1.0" encoding="utf-8"?>
<!-- 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
-->
<?xml-stylesheet type="text/xsl" href="https://rollerweblogger.org/roller-ui/styles/rss.xsl" media="screen"?><rss version="2.0" 
  xmlns:dc="http://purl.org/dc/elements/1.1/"
  xmlns:atom="http://www.w3.org/2005/Atom" >
<channel>
  <title>Blogging Roller</title>
  <link>https://rollerweblogger.org/roller/</link>
    <atom:link rel="self" type="application/rss+xml" href="https://rollerweblogger.org/roller/feed/entries/rss?tags=ember" />
  <description>Dave Johnson on open web technologies, social software and software development</description>
  <language>en-us</language>
  <copyright>Copyright 2026</copyright>
  <lastBuildDate>Mon, 18 May 2026 08:23:39 +0000</lastBuildDate>
  <generator>Apache Roller 6.1.5</generator>
  <item>
    <guid isPermaLink="true">https://rollerweblogger.org/roller/entry/usergrid-ember-pt-2</guid>
    <title>Usergrid and Ember.js - part 2</title>
    <dc:creator>Dave Johnson</dc:creator>
    <link>https://rollerweblogger.org/roller/entry/usergrid-ember-pt-2</link>
    <pubDate>Mon, 26 Jan 2015 10:23:01 +0000</pubDate>
    <category>Web Development</category>
    <category>asf</category>
    <category>baas</category>
    <category>ember</category>
    <category>javascript</category>
    <category>usergrid</category>
<description>&lt;p&gt;In &lt;a href=&quot;http://rollerweblogger.org/roller/entry/usergrid-ember-pt-2&quot;&gt;part one&lt;/a&gt;, I explained the basics of the example Usergrid-Ember &amp;quot;Checkin&amp;quot; app, how the index page is displayed and how login is implemented. In part two, I&amp;#39;ll explain how Ember.js can be hooked into the Usergrid REST API to store and query JSON objects.&lt;/p&gt;

&lt;a href=&quot;http://emberjs.com&quot;&gt;&lt;img src=&quot;https://rollerweblogger.org/roller/mediaresource/87879b47-6b14-4c18-a17e-576a68bf62a0&quot; alt=&quot;Ember logo&quot; align=&quot;right&quot;&gt;&lt;/a&gt;

&lt;p&gt;Ember.js includes a feature referred to as &lt;a href=&quot;http://emberjs.com/guides/models&quot;&gt;Ember-Data&lt;/a&gt;, which provides a persistence interface for storing and retrieving JavaScript objects that could be stored in memory, or stored on a server and accessed via REST API.&lt;/p&gt;

&lt;p&gt;To use Ember-Data with your REST API you&amp;#39;ve got to define an Ember-Data model and add an Ember-Data REST adapter. If your REST API differs from what Ember-Data expects then you will probably have to extend the built-in REST adapter to handle your URL pattens, and extend the built-in REST serializer to handle your JSON format. By extending Ember-Data in this way, you can use it to store and query data from Usergrid without using the Usergrid JavaScript SDK at all. Below I&amp;#39;ll explain what I had to do to make the Checkin app&amp;#39;s Activities collection available via Ember-Data.&lt;/p&gt;


&lt;h3&gt;Define Ember-Data models&lt;/h3&gt;

&lt;p&gt;Ember-Data expects each of your REST API collections to have a defined data model, one that extends the DS.Model class. Here&amp;#39;s what I added for the Activities collection:&lt;/p&gt;

&lt;p&gt;&lt;b&gt;From app.js (&amp;lt;a href=&amp;quot;https://github.com/snoopdave/usergrid-ember/blob/v2/js/app.js#L18&amp;quot;
&amp;gt;link)&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;brush:js&quot;&gt;
App.Activity = DS.Model.extend({
  uuid: DS.attr(&amp;#39;string&amp;#39;),
  type: DS.attr(&amp;#39;string&amp;#39;),
  content: DS.attr(&amp;#39;string&amp;#39;),
  location: DS.attr(&amp;#39;string&amp;#39;),
  created: DS.attr(&amp;#39;date&amp;#39;),
  modified: DS.attr(&amp;#39;date&amp;#39;),
  actor: DS.attr(&amp;#39;string&amp;#39;),
  verb: DS.attr(&amp;#39;string&amp;#39;),
  published: DS.attr(&amp;#39;date&amp;#39;),
  metadata: DS.attr(&amp;#39;string&amp;#39;)
});
&lt;/pre&gt;


&lt;h3&gt;Create a custom RESTAdapter&lt;/h3&gt;

&lt;p&gt;The Ember-Data REST adapter expects a REST API to follow some common conventions for URL patterns and for JSON data formats. For example, if your REST API provides a collection of cats then Ember-Data will expect your REST API to work like so:


&lt;p&gt;&lt;b&gt;What Ember-Data expects for a cats collection:&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;GET /cats&lt;/b&gt; - get collection of cats&lt;/li&gt;
&lt;li&gt;&lt;b&gt;POST /cats&lt;/b&gt; - create new cat.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;GET /cats/{cat-id}&lt;/b&gt; - get cat specified by ID.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;PUT /cats/{cat-id}&lt;/b&gt; - update cat specified by ID.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;DELETE /cats/{cat-id}&lt;/b&gt; - delete cat specified by ID.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Usergrid follows the above conventions for collections, but there are some exceptions. For example, the Usergrid Activities collection. A GET on the &lt;code&gt;/activities&lt;/code&gt; path will return the Activities of the users that you (i.e. the currently authenticated user) follow. You don&amp;#39;t POST new activities there, instead you post to your own Activities collection at the path &lt;code&gt;/users/{your-user-id}/activities&lt;/code&gt;. It works like this:&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Usergrid&amp;#39;s Activities collection:&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;GET /activities&lt;/b&gt; - get Activities of all users that you follow.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;POST /user/{user-id}/activities&lt;/b&gt; - create new Activity for user specified by ID&lt;/li&gt;
&lt;li&gt;&lt;b&gt;GET /user/{user-id}/activities&lt;/b&gt; - get Activities for one specific user.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To adapt the Activities collection to Ember-Data, I decided to create a new model called NewActivity. A NewActivity represents the data needed to create a new Activity, here&amp;#39;s the model:&lt;/p&gt;

&lt;p&gt;&lt;b&gt;From app.js (&amp;lt;a href=&amp;quot;https://github.com/snoopdave/usergrid-ember/blob/v2/js/app.js#L132&amp;quot;
&amp;gt;Link)&lt;/b&gt;&lt;/p&gt;&lt;pre class=&quot;brush:js&quot;&gt;
// Must have a special model for new activity because new 
// Activities must be posted to the path /{org}/{app}/users/activities, 
// instead of the path /{org}/{app}/activities as Ember-Data expects.
App.NewActivity = DS.Model.extend({
  content: DS.attr(&amp;#39;string&amp;#39;),
  location: DS.attr(&amp;#39;string&amp;#39;),
  actor: DS.attr(&amp;#39;string&amp;#39;),
  verb: DS.attr(&amp;#39;string&amp;#39;)
});
&lt;/pre&gt;

&lt;p&gt;Then, in Checkin&amp;#39;s custom REST adapter, I added logic to the &lt;code&gt;pathForType()&lt;/code&gt; function to ensure that NewActivities are posted to the correct path. Here&amp;#39;s the adapter:&lt;/p&gt;

&lt;p&gt;&lt;b&gt;From app.js (&amp;lt;a href=&amp;quot;https://github.com/snoopdave/usergrid-ember/blob/v2/js/app.js#L40&amp;quot;
&amp;gt;Link)&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;brush:js&quot;&gt;
App.ApplicationAdapter = DS.RESTAdapter.extend({

  host: Usergrid.getAppUrl(),

  headers: function() { 
    if ( localStorage.getItem(&amp;quot;access_token&amp;quot;) ) {
      return { &amp;quot;Authorization&amp;quot;: &amp;quot;Bearer &amp;quot; 
          + localStorage.getItem(&amp;quot;access_token&amp;quot;) }; 
    } 
    return {};
  }.property().volatile(), // ensure value not cached

  pathForType: function(type) {
    var ret = Ember.String.camelize(type);
    ret = Ember.String.pluralize(ret);

    if ( ret == &amp;quot;newActivities&amp;quot; ) {
      // Must have a special logic here for new activity 
      // because new Activities must be posted to the 
      // path /{org}/{app}/users/activities, instead of the 
      // path /{org}/{app}/activities as Ember-Data expects.
      ret = &amp;quot;/users/&amp;quot; + Usergrid.user.username + &amp;quot;/activities&amp;quot;;
    }
    return ret;
  }

});
&lt;/pre&gt;

&lt;p&gt;You can see a couple of other interesting things in the example above. First, there&amp;#39;s the &lt;code&gt;host&lt;/code&gt; field which specifies the base-URL of the REST API for the Checkin app. Next, there&amp;#39;s the &lt;code&gt;headers()&lt;/code&gt; function, which ensures that every request carries the &lt;code&gt;access_token&lt;/code&gt; that was acquired during login.&lt;/p&gt;


&lt;h3&gt;Create a custom RESTSerializer&lt;/h3&gt;

&lt;p&gt;Ember-Data also has expectations about the JSON format returned by a REST API. Unfortunately, what Ember-Data expects and what Usergrid provides are quite different. The two examples below illustrate the differences:&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Ember-Data vs. Usergrid JSON formats&lt;/b&gt;&lt;/p&gt;
&lt;table&gt;
   &lt;tr&gt;
      &lt;td valign=&quot;top&quot;&gt;

&lt;p&gt;Ember-Data expects collections like this:&lt;/p&gt;
&lt;pre&gt;
{
   cats: [{
       &amp;quot;id&amp;quot;: &amp;quot;6b2360d0&amp;quot;,
       &amp;quot;name&amp;quot;: &amp;quot;enzo&amp;quot;,
       &amp;quot;color&amp;quot;: &amp;quot;orange&amp;quot;
   },{
       &amp;quot;id&amp;quot;: &amp;quot;a01dfaa0&amp;quot;,
       &amp;quot;name&amp;quot;: &amp;quot;bertha&amp;quot;,
       &amp;quot;color&amp;quot;: &amp;quot;tabby&amp;quot;
   }]
}






&lt;/pre&gt;

      &lt;/td&gt;
      &lt;td&gt;&lt;/td&gt;
      &lt;td valign=&quot;top&quot;&gt;

&lt;p&gt;Usergrid returns collections like this:&lt;/p&gt;
&lt;pre&gt;
{
   action: &amp;quot;get&amp;quot;,
   path: &amp;quot;/cats&amp;quot;,
   count: 2,
   entities: [{
       &amp;quot;uuid&amp;quot;: &amp;quot;6b2360d0&amp;quot;,
       &amp;quot;type&amp;quot;: &amp;quot;cat&amp;quot;,
       &amp;quot;name&amp;quot;: &amp;quot;enzo&amp;quot;,
       &amp;quot;color&amp;quot;: &amp;quot;orange&amp;quot;
   },{
       &amp;quot;uuid&amp;quot;: &amp;quot;a01dfaa1&amp;quot;,
       &amp;quot;type&amp;quot;: &amp;quot;cat&amp;quot;,
       &amp;quot;name&amp;quot;: &amp;quot;bertha&amp;quot;,
       &amp;quot;color&amp;quot;: &amp;quot;tabby&amp;quot;
   }]
}

&lt;/pre&gt;

      &lt;/td&gt;
   &lt;/tr&gt;
   &lt;tr&gt;
      &lt;td valign=&quot;top&quot;&gt;

&lt;p&gt;Ember-Data expects individual objects like this:&lt;/p&gt;
&lt;pre&gt; 
{
   cat: {
       &amp;quot;id&amp;quot;: &amp;quot;a01dfaa0&amp;quot;,
       &amp;quot;name&amp;quot;: &amp;quot;bertha&amp;quot;,
       &amp;quot;color&amp;quot;: &amp;quot;tabby&amp;quot;
   }
}
&lt;/pre&gt; 

      &lt;/td&gt;
      &lt;td&gt;&lt;/td&gt;
      &lt;td valign=&quot;top&quot;&gt;

&lt;p&gt;Usergrid returns individual objects like this:&lt;/p&gt;
&lt;pre&gt; 
{
   &amp;quot;id&amp;quot;: &amp;quot;a01dfaa0&amp;quot;,
   &amp;quot;type&amp;quot;: &amp;quot;cat&amp;quot;,
   &amp;quot;name&amp;quot;: &amp;quot;bertha&amp;quot;,
   &amp;quot;color&amp;quot;: &amp;quot;tabby&amp;quot;
}

&lt;/pre&gt; 

      &lt;/td&gt;
   &lt;/tr&gt;
&lt;/table&gt;

&lt;p&gt;You can see two differences above. Ember-Data expects JSON objects to be returned with a &amp;quot;type key&amp;quot; which you can see above: the &amp;quot;cats&amp;quot; field in the collection and the &amp;quot;cat&amp;quot; field in the individual object. Also, Ember-Data expects an object&amp;#39;s ID field to be named &amp;quot;id&amp;quot; but Usergrid returns it as &amp;quot;uuid.&amp;quot;&lt;/p&gt;

&lt;p&gt;The deal with these differences, the Checkin app extends Ember-Data&amp;#39;s &lt;code&gt;DS.RESTSerializer&lt;/code&gt;. Here&amp;#39;s the code:&lt;/p&gt;

&lt;p&gt;&lt;b&gt;From app.js (&amp;lt;a href=&amp;quot;https://github.com/snoopdave/usergrid-ember/blob/v2/js/app.js#L75&amp;quot;
&amp;gt;Link)&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;brush:js&quot;&gt;
App.ApplicationSerializer = DS.RESTSerializer.extend({

  // Extract Ember-Data array from Usergrid response
  extractArray: function(store, type, payload) {

    // Difference: Usergrid does not return wrapper object with 
    // type-key. So here we grab the Usergrid Entities and stick 
    // them under a type-key
    var typeKey = payload.path.substring(1);
    payload[ typeKey ] = payload.entities;

    // Difference: Usergrid returns ID in &amp;#39;uuid&amp;#39; field, Ember-Data 
    // expects &amp;#39;id&amp;#39;. So here we add an &amp;#39;id&amp;#39; field for each Entity, 
    // with its &amp;#39;uuid&amp;#39; value.
    for ( var i in payload.entities ) {
      if ( payload.entities[i] &amp;&amp; payload.entities[i].uuid ) {
        payload.entities[i].id = payload.entities[i].uuid;
      }
    }
    return this._super(store, type, payload);
  },

  // Serialize Ember-Data object to Usergrid compatible JSON format
  serializeIntoHash: function( hash, type, record, options ) {

    // Usergrid does not expect a type-key
    record.eachAttribute(function( name, meta ) {
      hash[name] = record.get(name);
    });

    return hash;
  }
});
&lt;/pre&gt;

&lt;p&gt;In the code above you can see how the &lt;code&gt;extractArray()&lt;/code&gt; method moves the &amp;quot;entities&amp;quot; collection returned by Usergrid into a type-key field as expected by Ember-Data and how it copies the &amp;quot;uuid&amp;quot; field to add the &amp;quot;id&amp;quot; field that Ember-Data expects. &lt;/p&gt;

&lt;p&gt;We also need to transform the data that Ember-Data sends to Usergrid. You can see this above in the &lt;code&gt;serializeInHash()&lt;/code&gt; function, which ensures that when data is POSTed or PUT to Usergrid, the type key is removed because that&amp;#39;s what Usergrid expects.&lt;/p&gt;


&lt;h3&gt;Implementing Add-Checkin&lt;/h3&gt;

&lt;p&gt;To implement Add-Checkin, I added an HTML template called &amp;quot;add-checkin&amp;quot; to Checkin&amp;#39;s index.html file. The template displays an Add-Checkin form with two fields: one for content and one for the location. Here&amp;#39;s what it looks like in all its modal glory:&lt;/p&gt;

&lt;br&gt;
&lt;p&gt;
&lt;img src=&quot;https://rollerweblogger.org/roller/mediaresource/5bc05437-f090-409e-90e4-c0fd978ea3ca&quot; alt=&quot;screenshot of add-checkin page&quot;&gt;
&lt;/p&gt;
&lt;br&gt;

&lt;p&gt;Both fields are simple strings (someday I&amp;#39;d like to extend Checkin to use location information from the browser). I won&amp;#39;t go into detail here, but it took a bit of research to figure out how to make a Bootstrap modal dialog work with Ember.js. Below you can see the add-checkin controller, which provides a &lt;code&gt;save()&lt;/code&gt; function to save a new checkin.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;From app.js (&amp;lt;a href=&amp;quot;https://github.com/snoopdave/usergrid-ember/blob/v2/js/app.js#L390&amp;quot;
&amp;gt;Link&lt;/b&gt;)&lt;/p&gt;
&lt;pre class=&quot;brush:js&quot;&gt;
App.AddCheckinModalController = Ember.ObjectController.extend({

  actions: {

    save: function( inputs ) {

      var content = inputs.content;
      var location = inputs.location;
      var target = this.get(&amp;quot;target&amp;quot;);

      var activity = this.store.createRecord( &amp;quot;NewActivity&amp;quot;, {
        content: content,
        location: location,
        verb: &amp;quot;checkin&amp;quot;,
        actor: {
          username: Usergrid.user.username
        }
      });

      activity.save().then(
        function( success ) { 
          alert(&amp;quot;Saved&amp;quot;); 
        },
        function( error ) { 
          alert(&amp;quot;Error &amp;quot; + error.responseJSON.error_description); 
        }
      ); 

    } 
  }
});
&lt;/pre&gt;

&lt;p&gt;In the code above you can see how easy it is to access Usergrid data via Ember-Data now that we&amp;#39;ve got our custom REST adapter and serializer in place. We create a new Activity with a call to &lt;code&gt;this.store.createRecord()&lt;/code&gt; and to save it all we need to do is &lt;code&gt; activity.save()&lt;/code&gt;.&lt;/p&gt;


&lt;h4&gt;Time to wrap up...&lt;/h4&gt;

&lt;p&gt;To sum things up, here are some closing thoughts and observations.&lt;/p&gt; 

&lt;ul&gt;
   &lt;li&gt;If you are considering JavaScript MVC frameworks, then Ember.js is definitely worthy of  your consideration. The documentation makes it easy to learn and the community is friendly and helpful.&lt;/li&gt;
   &lt;li&gt;It would be great for Usergrid to provide an Ember.js SDK that makes it really easy to build apps with Ember.js and Usergrid.&lt;/li&gt;
   &lt;li&gt;Ember-Data is an integral part of Ember.js, something that you need to do pretty much anything, but it is treated as a separate package with separate documentation. That is somewhat confusing for a new user.&lt;/li&gt;
   &lt;li&gt;Ember-Data does not include built-in form validation so if your app includes a large number of non-trivial  forms, then you may prefer AngularJS over Ember.js. 
   &lt;li&gt;There is a &lt;a href=&quot;https://github.com/dockyard/ember-validations&quot;&gt;form validation plugin&lt;/a&gt; for Ember.js, but it requires the experimental &lt;a href=&quot;http://www.ember-cli.com&quot;&gt;Ember-CLI&lt;/a&gt; utility. I tried to use it, but Ember-CLI was unpleasnt enough that I gave up.&lt;/li&gt;
&lt;/li&gt;&lt;/ul&gt;

&lt;p&gt;I appreciate any feedback you might have about this article, the Usergrid-Ember project and Apache Usergrid. If you want to see how the whole Usergrid-Ember project fits together, find it on GitHub here: &lt;a href=&quot;https://github.com/snoopdave/usergrid-ember&quot;&gt;Usergrid-Ember&lt;/a&gt;. Next up, I&amp;#39;ll write about my experiences using Apache Shiro to replace Spring Security in Apache Roller.&lt;/p&gt;&lt;/p&gt;</description>  </item>
</channel>
</rss>