<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>Ceriously... The Blog of Cerebris</title>
  <id>http://www.cerebris.com/blog/</id>
  <link href="http://www.cerebris.com/blog/"/>
  <link href="http://www.cerebris.com/blog/feed.xml" rel="self"/>
  <updated>2019-06-04T00:00:00Z</updated>
  <author>
    <name>Cerebris Corporation</name>
  </author>
  <entry>
    <title>Ember.js 2019 Roadmap</title>
    <link rel="alternate" href="http://www.cerebris.com/blog/2019/06/04/emberjs-2019/"/>
    <id>http://www.cerebris.com/blog/2019/06/04/emberjs-2019/</id>
    <published>2019-06-04T00:00:00Z</published>
    <updated>2019-06-04T00:00:00Z</updated>
    <author>
      <name>Dan Gebhardt</name>
    </author>
    <summary type="html">&lt;p&gt;The soon-to-be-finalized Octane edition of Ember brings with it a number of modernizations and enhancements that make the framework feel lighter, more tightly tied to "The Platform", and simply more joyful to use. This next year presents a wonderful...&lt;/p&gt;</summary>
    <content type="html">&lt;p&gt;The soon-to-be-finalized Octane edition of Ember brings with it a number of modernizations and enhancements that make the framework feel lighter, more tightly tied to &amp;quot;The Platform&amp;quot;, and simply more joyful to use. This next year presents a wonderful opportunity to double down on the progress from Octane and continue to modernize Ember itself and the apps we write with the framework.&lt;/p&gt;

&lt;p&gt;This post is an answer to the &lt;a href="https://blog.emberjs.com/2019/05/20/ember-2019-roadmap-call-for-posts.html"&gt;Call for Blog Posts&lt;/a&gt; intended to inform Ember&amp;#39;s 2019 Roadmap. As a member of the Framework Core Team, I feel that I have a particular responsibility to answer this call. My suggestion this year is to focus on modularity and packaging, both at the framework and application levels. Some aspects are technical, some are related to learning, and some are even related to marketing. All suggestions are made with ❤️ to help Ember continue its positive trajectory! 🚀&lt;/p&gt;
&lt;h2&gt;Framework Modularity and Packaging&lt;/h2&gt;
&lt;p&gt;Ember has long been perceived as an all-or-nothing framework, and there&amp;#39;s no more obvious manifestation of this perception than the &lt;code&gt;ember-source&lt;/code&gt; package. If there&amp;#39;s a single change I&amp;#39;d like to see in Ember over the next year, it would be to stop shipping &lt;code&gt;ember-source&lt;/code&gt; and move to multiple packages in the &lt;code&gt;@ember&lt;/code&gt; scope. This would represent a firm commitment to the public modularization of Ember and allow us to deliver on the promise laid out in the 2017 EmberConf keynote to &amp;quot;npm install your way to Ember&amp;quot;. Although, at this point, I would tweak that vision to &amp;quot;npm install Ember your way&amp;quot; so that it&amp;#39;s clear that the starting and ending points can both be considered &amp;quot;Ember&amp;quot;.&lt;/p&gt;
&lt;h3&gt;True Package Separation&lt;/h3&gt;
&lt;p&gt;Ember&amp;#39;s JavaScript modules API was released in October 2017 as part of &lt;a href="https://blog.emberjs.com/2017/10/11/ember-2-16-released.html"&gt;Ember.js 2.16&lt;/a&gt;. This release enabled us to stop accessing modules on the &lt;code&gt;Ember&lt;/code&gt; global in favor of targeted, &lt;code&gt;@ember&lt;/code&gt;-scoped modules, such as &lt;code&gt;@ember/routing&lt;/code&gt; and &lt;code&gt;@ember/service&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;To take the example from the v2.16 blog post, your component modules could move from this v2.15 version:&lt;/p&gt;
&lt;div class="highlight javascript "&gt;&lt;div class="scroller"&gt;&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td class="line-numbers"&gt;&lt;pre&gt;1
2
3
4
5
6
&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="reserved"&gt;import&lt;/span&gt; Ember from &lt;span class="string"&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;span class="content"&gt;ember&lt;/span&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;;

&lt;span class="reserved"&gt;export&lt;/span&gt; &lt;span class="keyword"&gt;default&lt;/span&gt; Ember.Component.extend({
  &lt;span class="key"&gt;session&lt;/span&gt;: Ember.inject.service(),
  &lt;span class="key"&gt;title&lt;/span&gt;: &lt;span class="string"&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;span class="content"&gt;The Curious Case&lt;/span&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
});
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;To this v2.16 version:&lt;/p&gt;
&lt;div class="highlight javascript "&gt;&lt;div class="scroller"&gt;&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td class="line-numbers"&gt;&lt;pre&gt;1
2
3
4
5
6
7
&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="reserved"&gt;import&lt;/span&gt; Component from &lt;span class="string"&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;span class="content"&gt;@ember/component&lt;/span&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;;
&lt;span class="reserved"&gt;import&lt;/span&gt; { inject as service } from &lt;span class="string"&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;span class="content"&gt;@ember/service&lt;/span&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;;

&lt;span class="reserved"&gt;export&lt;/span&gt; &lt;span class="keyword"&gt;default&lt;/span&gt; Component.extend({
  &lt;span class="key"&gt;session&lt;/span&gt;: service(),
  &lt;span class="key"&gt;title&lt;/span&gt;: &lt;span class="string"&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;span class="content"&gt;The Curious Case&lt;/span&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
});
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Even with this great leap forward in DX, these packages were not &amp;quot;true&amp;quot; packages published to npm. And this has not changed - they continue to be synthetic packages fully published in &lt;code&gt;ember-source&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;From the outside looking in, it may appear that it&amp;#39;s a trivial move to take one more step and just break apart &lt;code&gt;ember-source&lt;/code&gt; into packages, which are clearly already defined in a namespaced form. You may retain this belief after looking into Ember&amp;#39;s source and seeing &lt;a href="https://github.com/emberjs/ember.js/tree/master/packages/%40ember"&gt;those packages&lt;/a&gt; already listed in the &lt;code&gt;@ember&lt;/code&gt; namespace.&lt;/p&gt;

&lt;p&gt;However, as you can probably suspect, there will be more to this process than meets the eye. Much of Ember&amp;#39;s source remains in &lt;a href="https://github.com/emberjs/ember.js/tree/master/packages/%40ember/-internals"&gt;internal modules&lt;/a&gt; that represent cross-cutting or not fully factored concerns. Ideally, &lt;a href="https://github.com/emberjs/ember.js/tree/master/packages/%40ember/-internals/routing/lib"&gt;routing internals&lt;/a&gt; would be shipped together with &lt;code&gt;@ember/routing&lt;/code&gt; and not contained in a massive &lt;code&gt;@ember/-internals&lt;/code&gt; package (which has never been intended to be published as a package at all). The scope of the refactoring needed to do this right is why I believe this belongs on an annual roadmap rather than simply being a switch we can flip at a team meeting.&lt;/p&gt;

&lt;p&gt;Let&amp;#39;s delve into why I believe that true package separation will be worth the effort.&lt;/p&gt;
&lt;h3&gt;Align Learning with Packaging&lt;/h3&gt;
&lt;p&gt;Incremental adoption of capabilities provides an approachable path to learning that keeps control in the hands of the learner. Instead of diving (or being thrown) into the deep end, developers should be able to dip their toes into Ember, gradually acclimate, and then decide how much further they want to go.&lt;/p&gt;

&lt;p&gt;Ember should be taught as a component-first framework that doesn&amp;#39;t require routing, controllers, data, or much of anything else to get started.&lt;/p&gt;

&lt;p&gt;I can easily imagine the guides incorporating this approach through phrases such as:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Routing is an important part of multi-page web applications. You can introduce routing into your Ember application by running: &lt;code&gt;npm install @ember/routing&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The guides could go on to explain that installing &lt;code&gt;@ember/routing&lt;/code&gt; will bring in other packages as dependencies, such as &lt;code&gt;@ember/controllers&lt;/code&gt;. This will clarify the role of controllers as a bridge between routes and components. By teaching that Ember&amp;#39;s core capabilities can be provided via core &lt;code&gt;@ember&lt;/code&gt;-scoped packages, we are both telling &lt;em&gt;and&lt;/em&gt; showing that Ember is modular.&lt;/p&gt;
&lt;h3&gt;Minimize Dependencies, Maximize Appeal&lt;/h3&gt;
&lt;p&gt;Historically, Ember has chosen to include capabilities by default that meet roughly 80% of the needs of web applications. However, if we apply this logic to every capability, there will be a further diminishing percentage for which this applies. After all, 80% x 80% x 80% x 80% &amp;lt; 50%.&lt;/p&gt;

&lt;p&gt;Let&amp;#39;s look at a couple examples.&lt;/p&gt;

&lt;p&gt;While I strongly believe that Ember Data should be designed to meet the data needs of 80% of web applications, I don&amp;#39;t think it should be included in the default blueprint. It would be much less surprising for developers new to Ember to begin using &lt;code&gt;fetch&lt;/code&gt; and then &amp;quot;upgrade&amp;quot; to Ember Data when they feel the need.&lt;/p&gt;

&lt;p&gt;Similarly, while I believe that Ember&amp;#39;s router may meet the routing needs of well over 80% of web applications, I also don&amp;#39;t believe that &lt;code&gt;@ember/routing&lt;/code&gt; should be included in the default blueprint. But doesn&amp;#39;t every &amp;quot;real app&amp;quot; need routing? I would say that&amp;#39;s the kind of question that leads to &lt;a href="https://en.wikipedia.org/wiki/Selection_bias"&gt;selection bias&lt;/a&gt; and missed opportunities.&lt;/p&gt;

&lt;p&gt;If we want to break the stereotype that Ember is only suitable for desktop applications with traditional routing needs that communicate primarily with REST APIs, then we should stop shipping a default blueprint that reflects that use case so well.&lt;/p&gt;
&lt;h3&gt;Experiments at Every Level&lt;/h3&gt;
&lt;p&gt;One of the benefits to package modularization is that it will open experiments at every layer of the framework.&lt;/p&gt;

&lt;p&gt;Someone will build a lightweight router for simple widgets. Someone else will build a stack-based router driven by state pushed from the server (see Alex Matchneer&amp;#39;s &lt;a href="https://www.dunningpostor.com/ember-rideshare/"&gt;ember-rideshare&lt;/a&gt; thought experiment).&lt;/p&gt;

&lt;p&gt;Wouldn&amp;#39;t it be better to continue to add features into &lt;code&gt;@ember/routing&lt;/code&gt; so that it can do it all? I certainly believe in the power of shared abstractions, but these take a long time to get right. And you can never figure out The Right Abstraction™️ based upon a sample size of one.&lt;/p&gt;

&lt;p&gt;I need to be clear that there&amp;#39;s no doubt that one of Ember&amp;#39;s primary strengths are its strong conventions. I&amp;#39;m sure that I&amp;#39;m not the only one who enjoys the comfort and productivity that comes from being able to drop into any Ember app and find my way around without guidance. So I&amp;#39;m in no way proposing that we abandon the important tenet of &amp;quot;convention over configuration&amp;quot;. Rather, I strongly believe that any fragmentations that appear in the community due to experimentation will be driven by divergences in actual needs. This has been proven out in the spaces that already support experimentation. Plenty of Ember developers use JSON:API, while many others use GraphQL. Ember developers work on desktop apps and mobile web apps, browser and native. We have a pretty big tent, and I think it will get bigger and better through more openness and experimentation.&lt;/p&gt;
&lt;h3&gt;The Pitch&lt;/h3&gt;
&lt;p&gt;I personally believe that the &amp;quot;batteries included&amp;quot; marketing pitch is a bit off. I&amp;#39;d prefer something that sounds less like we&amp;#39;re sending you the kitchen sink whether you want it or not. In my opinion, a better pitch would emphasize that, between Ember&amp;#39;s core packages and its ecosystem of addons, a massive matrix of capabilities is available to choose from depending upon your needs. Perhaps &amp;quot;Ember has an answer&amp;quot;. Or &amp;quot;The composable framework&amp;quot;.&lt;/p&gt;
&lt;h2&gt;Application Modularity and Packaging&lt;/h2&gt;
&lt;p&gt;I consider Ember&amp;#39;s developer experience to be second-to-none. We are spoiled by Ember CLI, its generators, blueprints, test framework, and ecosystem of addons. Yet there are some aspects of building Ember applications that could no doubt be improved.&lt;/p&gt;
&lt;h3&gt;New File System&lt;/h3&gt;
&lt;p&gt;William Faulkner wrote that &amp;quot;In writing, you must kill all your darlings&amp;quot;. And I would say that, in software, we are surprisingly gleeful about killing our own code. The reason for our glee is that we always believe we are replacing it with something better or (best of all) no code at all.&lt;/p&gt;

&lt;p&gt;Thus, it is with a light heart that I bid adieau to &lt;a href="https://emberjs.github.io/rfcs/0143-module-unification.html"&gt;Module Unification&lt;/a&gt;, an RFC that I toiled mightily upon after first joining the Core Team. The reasons I am untroubled by this are outlined by Tom Dale in his &lt;a href="https://blog.emberjs.com/2019/03/11/update-on-module-unification-and-octane.html"&gt;Update on Module Unification&lt;/a&gt;. Simply put, the acceptance of template imports removes swaths of use cases that drove the original RFC&amp;#39;s design.&lt;/p&gt;

&lt;p&gt;I believe that we now have the opportunity to shape a &amp;quot;New File Layout&amp;quot; that is simpler and clearer than the one proposed as Module Unification. Hopefully, we can take the best aspects of that design that are still relevant and move forward quickly. A shared project structure is one of Ember&amp;#39;s strongest conventions, and I consider its evolution to be one of our highest priorities.&lt;/p&gt;
&lt;h3&gt;DI is Dead, Long Live DI&lt;/h3&gt;
&lt;p&gt;The role of dependency injection (&amp;quot;DI&amp;quot;) in Ember did not also die with the introduction of template imports. Rather, we are trimming the sails and bit and not using DI where it is not needed. In other words, we should not add dynamic degrees of freedom in places where simple static dependencies will do. We&amp;#39;ve come to a pretty strong consensus that dynamism is not needed when resolving components and helpers, and in fact causes more harm than good.&lt;/p&gt;

&lt;p&gt;I believe that DI remains a powerful tool for Ember that could be improved. I think the time is right to re-evaluate where and how it is used.&lt;/p&gt;
&lt;h3&gt;Embroider&lt;/h3&gt;
&lt;p&gt;Last but not least, this is undoubtedly the year of &lt;a href="https://github.com/embroider-build/embroider/blob/master/README.md"&gt;Embroider&lt;/a&gt;! 🎉&lt;/p&gt;

&lt;p&gt;&lt;a href="https://twitter.com/eaf4"&gt;Ed Faulkner&lt;/a&gt; (no relation to William, AFAIK) has been working tirelessly on this modern rethink of Ember&amp;#39;s build system. Embroider introduces a pipeline that includes a packaging step that can be fulfilled by any industry standard tool - Webpack, Rollup, or Parcel. This unlocks automatic npm imports, tree-shaking, and lazy-loading of segments of your application.&lt;/p&gt;

&lt;p&gt;I&amp;#39;m thankful for all the modernizations and simplications Embroider will bring. Personally, I&amp;#39;m most looking forward to finally deleting all the custom build processing and lazy-loading code written for &lt;a href="http://ember-engines.com"&gt;ember-engines&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Summary&lt;/h2&gt;
&lt;p&gt;Octane brought a number of massive ergonomic improvements to the day-to-day developer experience &lt;em&gt;within individual modules&lt;/em&gt;, from Glimmer templates and components to native classes. Now it&amp;#39;s time for us to focus on how we structure and bind and package those modules, both at the framework and application levels.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>What's New in JSONAPI::Resources</title>
    <link rel="alternate" href="http://www.cerebris.com/blog/2019/03/12/jsonapi-resources-update/"/>
    <id>http://www.cerebris.com/blog/2019/03/12/jsonapi-resources-update/</id>
    <published>2019-03-12T00:00:00Z</published>
    <updated>2019-03-12T00:00:00Z</updated>
    <author>
      <name>Larry Gebhardt</name>
    </author>
    <summary type="html">&lt;p&gt;I haven't blogged about JSONAPI::Resources ("JR") since &lt;a href="/blog/2014/08/22/introducing-jsonapi-resources/"&gt;it was introduced&lt;/a&gt; over four years ago. Communication on our blog has unfortunately taken a backseat to many other objectives, including new features for JR, work on a soon-to-be-released product...&lt;/p&gt;</summary>
    <content type="html">&lt;p&gt;I haven&amp;#39;t blogged about JSONAPI::Resources (&amp;quot;JR&amp;quot;) since &lt;a href="/blog/2014/08/22/introducing-jsonapi-resources/"&gt;it was introduced&lt;/a&gt; over four years ago. Communication on our blog has unfortunately taken a backseat to many other objectives, including new features for JR, work on a soon-to-be-released product (why we started this in the first place), and consulting to keep the lights on. However, I&amp;#39;d like to get back to communicating here on a more regular basis.&lt;/p&gt;
&lt;h3&gt;Growth and maturity&lt;/h3&gt;
&lt;p&gt;Since JR&amp;#39;s introduction both its capabilities and its community have grown substantially. Support for the major features of the JSON:API spec has been added over many releases. Customizing the behavior of resources has become cleaner. Adding callables to individual filters, sorts, and soon relationships has replaced overriding the core methods of the library, which has improved the clarity of code that defines resources. Another huge win was the addition of caching support in v0.9, which can make a big difference in performance for frequently requested resources. And, perhaps most importantly for me personally, JR is working well as the foundation for the backend of the product we&amp;#39;re building.&lt;/p&gt;
&lt;h3&gt;New core team members&lt;/h3&gt;
&lt;p&gt;&lt;a href="https://github.com/barelyknown"&gt;Sean Devine&lt;/a&gt; joined JR&amp;#39;s core team in the very early days of the project. Sean&amp;#39;s a long time contributor who&amp;#39;s used JR to help build his construction logistics business, &lt;a href="https://www.x-b-e.com"&gt;XBE&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/scottgonzalez"&gt;Scott González&lt;/a&gt; just recently joined the core team. If you&amp;#39;ve ever had a question in our &lt;a href="https://gitter.im/cerebris/jsonapi-resources"&gt;Gitter community&lt;/a&gt;, chances are that Scott was there to help you out. I&amp;#39;m really grateful to have Scott on the core team to help the project at a whole other level.&lt;/p&gt;
&lt;h3&gt;Improved documentation&lt;/h3&gt;
&lt;p&gt;We&amp;#39;ve added a &lt;a href="http://jsonapi-resources.com"&gt;documentation site&lt;/a&gt; where you can get updated on all the features that are now in the project. A &lt;a href="https://gitter.im/cerebris/jsonapi-resources"&gt;Gitter community&lt;/a&gt; has been setup for chat and support. There you can usually get an answer quickly as there are multiple people watching the conversations and willing help out.&lt;/p&gt;
&lt;h2&gt;v0.10.0 is right around the corner&lt;/h2&gt;
&lt;p&gt;JR is now up to stable v0.9.5, with v0.10 currently in beta. Now seems like a good time to discuss what&amp;#39;s coming in the v0.10 release and beyond.&lt;/p&gt;
&lt;h3&gt;Resource finders&lt;/h3&gt;
&lt;p&gt;The &lt;code&gt;JSONAPI::Resource&lt;/code&gt; class was originally conceived as a thin layer on top of &lt;code&gt;ActiveRecord&lt;/code&gt; models. &lt;code&gt;JSONAPI::Resource&lt;/code&gt; would proxy down to the model for attributes, compose &lt;code&gt;ActiveRecord::Relation&lt;/code&gt; expressions for resource searching and joins between resources over defined relationships. Some of the logic for how to perform these tasks was specific to models based on a SQL database which could use &lt;code&gt;ActiveRecord::Relation&lt;/code&gt;. This resulted in a lot of &lt;code&gt;ActiveRecord::Relation&lt;/code&gt; code in the &lt;code&gt;JSONAPI::Resource&lt;/code&gt; class, which makes it difficult to back resources with ORMs other than &lt;code&gt;ActiveRecord&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In v0.10 the functionality that interacts with the data stores has been abstracted into modules called resource finders. Resource finders work with the Processor to support finding resources while applying all the requested sorting, filtering, joining, and pagination.&lt;/p&gt;
&lt;h4&gt;ActiveRelationResourceFinder&lt;/h4&gt;
&lt;p&gt;As of this writing the only resource finder is the &lt;code&gt;ActiveRelationResourceFinder&lt;/code&gt;. This is not a simply an extraction of the old resource code, but rather reworks the methods used to find resources and the related resources for a request. This resource finder approaches the finding of resources in several phases. The first phase searches for the identities and cache fields using pluck. This results in a very fast query to the database without instantiating model instances. When included resources are requested their identities are also found and added to a &lt;code&gt;ResourceSet&lt;/code&gt;. The next phase, optionally, looks for already serialized resources from the cache and adds them to the resource set, avoiding instantiation and serialization of those models. Finally all remaining models are loaded by identity and serialized. By breaking the process into phases we gain efficiencies when communicating in bulk with the cache and with the database for each resource type, as well as minimizing model instantiation and serialization.&lt;/p&gt;
&lt;h3&gt;What&amp;#39;s left for the beta period?&lt;/h3&gt;
&lt;p&gt;There&amp;#39;s still a bit more to do before v0.10 is out of beta. Since support for additional resource finders is planned, we should allow resources with relationships to other resources that use different resource finders. For example, these relationships might reference a remote API server or even resources stored in a document database. A few changes to the existing codebase will be needed to make this possible.&lt;/p&gt;
&lt;h2&gt;What&amp;#39;s next after v0.10.0? Sponsor a feature 🚀&lt;/h2&gt;
&lt;p&gt;Cerebris, which consists of just Dan and myself, has been self-funding the bulk of the development of JSONAPI::Resources since its inception. As you can probably imagine, this has been quite an undertaking for a two person firm, even with all the help from the other contributors (for which we are very grateful!). Frankly, we could use your help. It would be much appreciated if companies that are using JR could help out by sponsoring the development of new features. This would allow us to focus on the JSONAPI::Resources instead of consulting on completely separate projects. By allowing us to focus on this gem, you and the rest of the community can get useful new features more quickly, and you can focus on writing your own applications using JR.&lt;/p&gt;

&lt;p&gt;We&amp;#39;re still deciding what&amp;#39;s coming next. Honestly, many of our decisions will depend upon funding. These are the features we&amp;#39;re considering for upcoming releases:&lt;/p&gt;
&lt;h3&gt;Multiple operations&lt;/h3&gt;
&lt;p&gt;Supporting multiple operations per request is one of the most frequently requested features. Adding support for this in JR will first require finalizing support in the JSON:API spec. As one of the primary authors of the JSON:API spec, Dan is involved with shepherding the addition of &lt;a href="https://github.com/json-api/json-api/pull/1254"&gt;multiple operation support&lt;/a&gt; into JSON:API. Once the feature is finalized in the spec, support can be added to JSONAPI::Resources. The exact details required are TBD based on the final form of the spec. However the foundations of JR were designed with multiple operations in mind.&lt;/p&gt;
&lt;h3&gt;Expanded filter types&lt;/h3&gt;
&lt;p&gt;JSONAPI::Resources supports basic filtering on relationships by ids and text filters with an exact match for fields. Custom filters can be used, but those require custom programming by the API authors. Built in support for common filtering concepts would be a big improvement.&lt;/p&gt;

&lt;p&gt;For example making a text search case insensitive:&lt;/p&gt;
&lt;div class="highlight  "&gt;&lt;div class="scroller"&gt;&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td class="line-numbers"&gt;&lt;pre&gt;1
2
3
4
&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;class PostResource &amp;lt; JSONAPI::Resource
  attribute :title
  filter :title, case: :insensitive
end
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Currently this requires a custom &lt;code&gt;apply&lt;/code&gt; callable.&lt;/p&gt;
&lt;h3&gt;Profiles&lt;/h3&gt;
&lt;p&gt;&lt;a href="https://jsonapi.org/format/1.1/#profiles"&gt;Profiles&lt;/a&gt; have been added to JSON:API v1.1. Support for profiles in JSONAPI::Resources will require possibly significant changes. Beyond the obvious support for declaring and negotiating profiles, JR will also need to allow building custom profiles with unique capabilities. One example of this would be to allow the installation of different filtering profiles.&lt;/p&gt;
&lt;h3&gt;More resource finders&lt;/h3&gt;
&lt;p&gt;As alluded to above, JR could be extended to support additional resource finders. A prime candidate is a resource finder to support document databases such as MongoDB. Another possibility is a resource finder that proxies to another JSON:API server.&lt;/p&gt;
&lt;h3&gt;Custom features&lt;/h3&gt;
&lt;p&gt;If you have a custom feature in mind, please &lt;a href="/contact"&gt;get in touch&lt;/a&gt;. As long as it&amp;#39;s compliant with the JSON:API spec, we&amp;#39;ll probably be glad to work with you to add support directly to JR. We&amp;#39;re also open to working with you to build custom solutions that utilize JSONAPI::Resources to solve your business-specific needs.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>JSON:API 1.0</title>
    <link rel="alternate" href="http://www.cerebris.com/blog/2015/06/04/jsonapi-1-0/"/>
    <id>http://www.cerebris.com/blog/2015/06/04/jsonapi-1-0/</id>
    <published>2015-06-04T00:00:00Z</published>
    <updated>2015-06-04T00:00:00Z</updated>
    <author>
      <name>Dan Gebhardt</name>
    </author>
    <summary type="html">&lt;p&gt;&lt;a href="http://twitter.com/wycats"&gt;Yehuda Katz&lt;/a&gt; wrote the first draft of the &lt;a href="http://jsonapi.org/"&gt;JSON:API&lt;/a&gt; specification in May 2013 after hammering out the details in a long discussion with &lt;a href="https://twitter.com/steveklabnik"&gt;Steve Klabnik&lt;/a&gt; at RailsConf. JSON:API began as a codification of the shared expectations of a single server library...&lt;/p&gt;</summary>
    <content type="html">&lt;p&gt;&lt;a href="http://twitter.com/wycats"&gt;Yehuda Katz&lt;/a&gt; wrote the first draft of the &lt;a href="http://jsonapi.org/"&gt;JSON:API&lt;/a&gt; specification in May 2013 after hammering out the details in a long discussion with &lt;a href="https://twitter.com/steveklabnik"&gt;Steve Klabnik&lt;/a&gt; at RailsConf. JSON:API began as a codification of the shared expectations of a single server library for Rails, &lt;a href="https://github.com/rails-api/active_model_serializers"&gt;ActiveModel::Serializers&lt;/a&gt;, and a single JavaScript client library, &lt;a href="https://github.com/emberjs/data"&gt;Ember Data&lt;/a&gt;. &lt;em&gt;(As a bit of prehistory, I gave a &lt;a href="https://www.youtube.com/watch?v=rfQcmLLE3-w"&gt;talk&lt;/a&gt; about these shared expectations at the first EmberCamp in February 2013)&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Yehuda and Steve saw the value of separating these expectations into a formal specification that any client or server library could implement. Critically, the specification was encouraged to evolve in parallel, rather than in lockstep, with the original implementations. As a result, JSON:API has been influenced by developers both in and outside the original Ember and Rails communities from which it originated, which has undoubtedly resulted in a stronger spec with broader appeal.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;After two years, four release candidates, hundreds of pull requests and issues, and countless hours of discussion, the JSON:API specification has finally reached 1.0.&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;blockquote class="twitter-tweet" data-cards="hidden" lang="en"&gt;&lt;p lang="en" dir="ltr"&gt;It’s officially stable - we just tagged &lt;a href="https://twitter.com/jsonapi"&gt;@jsonapi&lt;/a&gt; v1.0! So grateful for our community’s contributions and patience. &lt;a href="https://t.co/fVWwmCl3y1"&gt;https://t.co/fVWwmCl3y1&lt;/a&gt;&lt;/p&gt;&amp;mdash; Dan Gebhardt (@dgeb) &lt;a href="https://twitter.com/dgeb/status/604295447214039041"&gt;May 29, 2015&lt;/a&gt;&lt;/blockquote&gt;

&lt;script async src="//platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now that JSON:API is stable and committed to allowing only additive changes, it&amp;#39;s poised to reach its full potential. At this unique time in the life of the specification, it seems appropriate to look both back at the journey to 1.0 and forward to the road ahead. But first a look at what makes JSON:API unique...&lt;/p&gt;
&lt;h2&gt;An Ambitious Specification&lt;/h2&gt;
&lt;p&gt;JSON:API is ambitious in purpose and scope: it defines both a media type (&lt;a href="http://www.iana.org/assignments/media-types/application/vnd.api+json"&gt;application/vnd.api+json&lt;/a&gt;) and rules for the usage of HTTP to fetch and modify resources represented by that media type. In this way JSON:API is similar to the &lt;a href="http://amundsen.com/media-types/collection/"&gt;Collection+JSON&lt;/a&gt; specification, but it has an even broader scope.&lt;/p&gt;

&lt;p&gt;By standardizing so many of the decisions around designing and building an API, JSON:API allows developers to focus on the design of their applications.&lt;/p&gt;
&lt;h3&gt;Goals&lt;/h3&gt;
&lt;p&gt;So what kind of API will you build by following JSON:API? The spec states its goals in this way:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;JSON:API is designed to minimize both the number of requests and the amount of data transmitted between clients and servers. This efficiency is achieved without compromising readability, flexibility, or discoverability.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;These goals are apparent throughout the design of the spec. Features such as compound documents, sparse fieldsets, and multi-field sorting allow clients to request exactly the data they need from a server and nothing more.&lt;/p&gt;

&lt;p&gt;For instance, let&amp;#39;s imagine an API for a blog that exposes articles, comments, and people as resources. A client might make the following request:&lt;/p&gt;
&lt;div class="highlight  "&gt;&lt;div class="scroller"&gt;&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td class="line-numbers"&gt;&lt;pre&gt;1
&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;GET /articles?include=comments,author&amp;amp;fields[people]=first-name,last-name&amp;amp;sort=-date
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;The above request will fetch all articles as well as their associated comments and authors. People resources (authors in this case) will only be returned with their first and last names. The article collection will be sorted by date, most recent first. The server will either return all the results together in a single response document, or it may paginate them. JSON:API also specifies how pagination links must be returned so that any compliant client will understand them.&lt;/p&gt;
&lt;h3&gt;A Focus on Hypermedia&lt;/h3&gt;
&lt;p&gt;JSON:API has really benefited from Steve Klabnik&amp;#39;s continued involvement. Steve is not only a standards junkie and &lt;a href="http://blog.steveklabnik.com/posts/2012-02-27-hypermedia-api-reading-list"&gt;hypermedia proponent&lt;/a&gt; - he is also literally &lt;a href="http://www.designinghypermediaapis.com/"&gt;writing the book on hypermedia APIs&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Thanks to Steve&amp;#39;s influence, it&amp;#39;s possible to build hypermedia APIs with JSON:API. Links can be added throughout JSON:API documents to specify canonical URLs for resources and their associated relationships. Clients can &amp;quot;crawl&amp;quot; links in an API just as your browser crawls links in HTML. By eliminating the need to hard-code URLs (or the logic to derive them), clients and servers become more loosely coupled and can more easily evolve.&lt;/p&gt;
&lt;h2&gt;Why JSON:API?&lt;/h2&gt;&lt;h3&gt;The Anti-Bikeshedding Weapon&lt;/h3&gt;
&lt;p&gt;JSON:API has gained entry to many organizations through its strong and consistent conventions that span almost every aspect of a &amp;quot;RESTful&amp;quot; API. Once a team starts to design an API, they often realize just how little guidance is provided by REST&amp;#39;s constraints. Rather than bikeshedding for hours over minor API design details, many teams have turned to JSON:API for guidance.&lt;/p&gt;

&lt;p&gt;The &lt;a href="http://jsonapi.org/format/"&gt;base JSON:API specification&lt;/a&gt; provides conventions for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;representing singular resources vs. resource collections&lt;/li&gt;
&lt;li&gt;identifying resources, including heterogenous (mixed type) resources&lt;/li&gt;
&lt;li&gt;including primary and related resources in a single compound document&lt;/li&gt;
&lt;li&gt;representing relationships between resources&lt;/li&gt;
&lt;li&gt;hypermedia links for resources, relationships, paginated collections, and more&lt;/li&gt;
&lt;li&gt;fetching, creating, updating, and deleting resources and relationships&lt;/li&gt;
&lt;li&gt;sparse fieldsets (i.e. limiting the fields included for each resource)&lt;/li&gt;
&lt;li&gt;sorting resources&lt;/li&gt;
&lt;li&gt;paginating primary and related resources&lt;/li&gt;
&lt;li&gt;filtering resources&lt;/li&gt;
&lt;li&gt;error statuses and data&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The JSON:API site also provides &lt;a href="http://jsonapi.org/recommendations/"&gt;recommendations&lt;/a&gt; that go beyond the scope of the base specification:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;naming members&lt;/li&gt;
&lt;li&gt;URL design&lt;/li&gt;
&lt;li&gt;filtering strategies&lt;/li&gt;
&lt;li&gt;supporting clients lacking PATCH&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It&amp;#39;s important to note that the base specification as well as the non-normative recommendations complement, and do not contradict, HTTP semantics.&lt;/p&gt;
&lt;h3&gt;A Thriving Ecosystem&lt;/h3&gt;
&lt;p&gt;While teams can immediately save time by adopting some of the hard-won conventions embodied by JSON:API, there are much broader and longer lasting benefits that can come from building a fully compliant API.&lt;/p&gt;

&lt;p&gt;An ecosystem of &lt;a href="http://jsonapi.org/implementations/"&gt;JSON:API compliant libraries&lt;/a&gt; that span many languages and frameworks is actively being developed. Whether you&amp;#39;re building a client or server, you should be able to lean on this ecosystem for assistance. Admittedly, many implementations are still works in progress, in no small part due to changes in JSON:API itself over the past two years. However, now that the spec has stabilized, it&amp;#39;s exciting to see implementations come into compliance with 1.0.&lt;/p&gt;
&lt;h2&gt;The Journey to 1.0&lt;/h2&gt;&lt;h3&gt;From Draft to Guideline to Specification&lt;/h3&gt;
&lt;p&gt;JSON:API started its life as a draft with a pretty narrow focus. As it grew in scope, it tended to do so inclusively. Some areas of the spec became so flexible that the matrix of possible options became untenable to fully implement (e.g. URL vs. ID styles, keying primary data by &lt;code&gt;data&lt;/code&gt; vs. resource type).&lt;/p&gt;

&lt;p&gt;JSON:API gradually became a set of fluid guidelines for developing APIs that was not focused enough to be called a spec.&lt;/p&gt;

&lt;p&gt;This &amp;quot;guideline phase&amp;quot; lasted for much of 2014. In retrospect, this period was truly invaluable because it allowed implementers to experiment and discover what worked and what didn&amp;#39;t. When Yehuda and I sat down together to rewrite the spec fully in December 2014, we were able to &amp;quot;pave the cowpaths&amp;quot; by choosing the well trodden paths that were working for implementors. We replaced many SHOULDs with MUSTs. The resulting RC2 draft of the spec was much tighter in focus and actually &lt;a href="https://github.com/json-api/json-api/pull/413"&gt;came quite close&lt;/a&gt; to being tagged 1.0 in March.&lt;/p&gt;
&lt;h3&gt;Polishing 1.0&lt;/h3&gt;
&lt;p&gt;As tempting as it was at the time, it&amp;#39;s a good thing that we didn&amp;#39;t abruptly release RC2 as JSON:API 1.0. Instead, we decided to give implementations a chance to catch up and test the new spec as a whole. We realized that there were a number of implementations already committed to compliance with the spec and that they needed more time to thoroughly vet its new incarnation.&lt;/p&gt;

&lt;p&gt;Two core contributors, &lt;a href="https://github.com/tkellen"&gt;Tyler Kellen&lt;/a&gt; and myself, have been actively developing compliant libraries. Tyler and his colleagues at &lt;a href="http://bocoup.com/"&gt;Bocoup&lt;/a&gt; have been building &lt;a href="https://github.com/endpoints"&gt;Endpoints&lt;/a&gt; for Node. At Cerebris, &lt;a href="https://twitter.com/larrygebhardt"&gt;Larry&lt;/a&gt; and I have been working on a server implementation for Rails, &lt;a href="https://github.com/cerebris/jsonapi-resources"&gt;JSONAPI::Resources&lt;/a&gt;, as well as a client implementation in JavaScript, &lt;a href="https://github.com/orbitjs/orbit.js"&gt;Orbit.js&lt;/a&gt;. During the final RC3 / RC4 phase, we all pushed to keep these libraries compliant with the spec to validate any changes.&lt;/p&gt;

&lt;p&gt;This final phase, perhaps more than any other, was truly a community effort. I&amp;#39;m especially grateful for the contributions of &lt;a href="https://github.com/ethanresnick"&gt;Ethan Resnick&lt;/a&gt;, &lt;a href="https://github.com/bintoro"&gt;Kalle Tuure&lt;/a&gt;, &lt;a href="https://github.com/hhware"&gt;hhware&lt;/a&gt;, &lt;a href="https://github.com/wvteijlingen"&gt;Ward van Teijlingen&lt;/a&gt;, and &lt;a href="https://github.com/ziege"&gt;Christoph Ziegenberg&lt;/a&gt;. They all really stepped up in the final months to raise issues and submit pull requests to ensure that JSON:API 1.0 was solid and would be extensible post-1.0. I also really, really appreciate all the time and effort that Tyler invested to help polish the final version of the spec.&lt;/p&gt;

&lt;p&gt;I&amp;#39;m so proud of, and grateful to, the JSON:API community for working together so well on difficult problems that have historically been the source of so many arguments. Thanks to you all for making 1.0 happen!&lt;/p&gt;
&lt;h2&gt;JSON:API 1.0+&lt;/h2&gt;
&lt;p&gt;I&amp;#39;m looking forward to seeing JSON:API reach its full potential as its ecosystem matures. It shouldn&amp;#39;t be long before 1.0 compliant implementations are available for most popular languages and frameworks. I&amp;#39;m also optimistic that compliance testing tools will soon be developed to help validate implementations.&lt;/p&gt;

&lt;p&gt;In a nice bit of symmetry, Ember Data is coming full circle to embrace JSON:API like never before. Ember Data&amp;#39;s JSON:API adapter and serializer are nearing full compliance. These layers will be very lean since the JSON:API format is also going to be used internally for normalized data. These changes should land with Ember Data 1.0.&lt;/p&gt;

&lt;p&gt;With its extensible structure, the spec itself is also poised to evolve in interesting (and non-breaking) ways post-1.0.&lt;/p&gt;

&lt;p&gt;For example, I expect that JSON:API will gain further hypermedia capabilities as the concept of links is extended.&lt;/p&gt;

&lt;p&gt;Another exciting possibility that we&amp;#39;ve explored are &lt;a href="http://jsonapi.org/extensions/"&gt;extensions&lt;/a&gt;. Although still experimental, extensions should allow clients and servers to negotiate for the support of features not included in the base spec. One such extension we&amp;#39;ve explored allows for &lt;a href="http://jsonapi.org/extensions/bulk/"&gt;bulk operations&lt;/a&gt; to be performed in a single request.&lt;/p&gt;

&lt;p&gt;In short, JSON:API 1.0 is just the beginning. It&amp;#39;s a great time to get involved with this project.&lt;/p&gt;

&lt;p&gt;&lt;hr /&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;If you&amp;#39;re interested in learning more about JSON:API, please check out the spec at &lt;a href="http://jsonapi.org/"&gt;jsonapi.org&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;If you have any questions or suggestions, please file an issue on &lt;a href="https://github.com/json-api/json-api/issues"&gt;JSON:API&amp;#39;s Github repo&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;And if you have any questions for me, please comment below.&lt;/em&gt;&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Introducing JSONAPI::Resources</title>
    <link rel="alternate" href="http://www.cerebris.com/blog/2014/08/22/introducing-jsonapi-resources/"/>
    <id>http://www.cerebris.com/blog/2014/08/22/introducing-jsonapi-resources/</id>
    <published>2014-08-22T00:00:00Z</published>
    <updated>2014-08-22T00:00:00Z</updated>
    <author>
      <name>Larry Gebhardt</name>
    </author>
    <summary type="html">&lt;p&gt;It's been a long time coming, but the &lt;a href="http://jsonapi.org"&gt;JSON:API&lt;/a&gt; spec is nearing a 1.0 release. &lt;a href="https://twitter.com/dgeb"&gt;Dan&lt;/a&gt; and I have been actively involved in helping to form this spec, which appeals to us because it is so ambitious and comprehensive. JSON:API goes beyond specifying a format...&lt;/p&gt;</summary>
    <content type="html">&lt;p&gt;It&amp;#39;s been a long time coming, but the &lt;a href="http://jsonapi.org"&gt;JSON:API&lt;/a&gt; spec is nearing a 1.0 release. &lt;a href="https://twitter.com/dgeb"&gt;Dan&lt;/a&gt; and I have been actively involved in helping to form this spec, which appeals to us because it is so ambitious and comprehensive. JSON:API goes beyond specifying a format for JSON payloads - &lt;em&gt;it also specifies how data should be fetched and modified.&lt;/em&gt; By standardizing so many of the decisions around designing and building an API, JSON:API allows developers to focus on the design of their applications. As JSON:API catches on, we&amp;#39;ll all benefit from the standardized tooling that develops for both clients and servers.&lt;/p&gt;

&lt;p&gt;Our initial contribution to this tooling is &lt;a href="https://github.com/cerebris/jsonapi-resources"&gt;JSONAPI::Resources&lt;/a&gt;, or &amp;quot;JR&amp;quot;. JR is a gem that allows Rails apps to easily support the JSON:API spec. As you may have guessed from the name, JR is resource-centric. You define resources for your application and JR can automatically fulfill requests to fetch and modify them. JR not only handles the serialization of responses, but also provides controllers that support methods to interact with the resource. By declaring resource relationships you can allow related resources to be retrieved in compound documents, and by specifying resource attributes you can control how the resource is represented to the API client.&lt;/p&gt;

&lt;p&gt;Until now, we&amp;#39;ve been using (and &lt;a href="https://speakerdeck.com/dgeb/building-ambitious-apis-with-ruby"&gt;recommending&lt;/a&gt; and &lt;a href="https://github.com/rails-api/active_model_serializers/graphs/contributors"&gt;contributing toward&lt;/a&gt;) &lt;a href="https://github.com/rails-api/active_model_serializers"&gt;ActiveModel::Serializers&lt;/a&gt;, or &amp;quot;AMS&amp;quot;, the Ruby library that has come closest to fulfilling the JSON:API spec. There are a couple reasons that we developed JR instead of continuing to work with AMS. First of all, AMS is not strictly focused on JSON:API, and has been out of compliance for some time. This is not a major hurdle and could be easily overcome by enabling a JSON:API mode in AMS, something which is already under discussion. The primary reason we developed JR is that AMS is focused on &lt;em&gt;serializers&lt;/em&gt; and not &lt;em&gt;resources&lt;/em&gt;. While serializers are just concerned with the representation of a model, resources can also act as a proxy to a backing model. In this way, JR can assist with fetching &lt;em&gt;and modifying&lt;/em&gt; resources, and can therefore handle all aspects of JSON:API.&lt;/p&gt;
&lt;h3&gt;Components&lt;/h3&gt;
&lt;p&gt;Let&amp;#39;s take a quick look at the major components of JSONAPI::Resources.&lt;/p&gt;
&lt;h4&gt;Resource&lt;/h4&gt;
&lt;p&gt;You can define the resources available through your API as subclasses of &lt;code&gt;JSONAPI::Resource&lt;/code&gt;. A resource definition looks very similar to the definition of a serializer in AMS. Resources form the core of JR and are used by many of its components.&lt;/p&gt;

&lt;p&gt;Let&amp;#39;s say we&amp;#39;re building a blog. Here&amp;#39;s a simple resource definition for posts:&lt;/p&gt;
&lt;div class="highlight  "&gt;&lt;div class="scroller"&gt;&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td class="line-numbers"&gt;&lt;pre&gt;1
2
3
4
5
6
7
&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;require 'json/api/resource'

class PostResource &amp;lt; JSONAPI::Resource
  attributes :id, :title, :body

  has_one :author
end
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;And here&amp;#39;s a corresponding author:&lt;/p&gt;
&lt;div class="highlight  "&gt;&lt;div class="scroller"&gt;&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td class="line-numbers"&gt;&lt;pre&gt;1
2
3
4
5
&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;class AuthorResource &amp;lt; JSONAPI::Resource
  attributes :id, :name

  has_many :posts
end
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;All declared attributes can, by default, be accessed through the API. There are also methods on a resource that you can implement to control which of the attributes are creatable, updateable, and fetchable. Any attribute on the underlying object that isn&amp;#39;t declared in the resource definition will not be available through the resource.&lt;/p&gt;

&lt;p&gt;Relationships support options to set different class names and keys from the resource names. In addition, a relationship can be treated &amp;quot;as a set&amp;quot; for &lt;code&gt;create&lt;/code&gt; and &lt;code&gt;update&lt;/code&gt; purposes.&lt;/p&gt;

&lt;p&gt;In the following example, tags are defined with the &lt;code&gt;acts_as_set&lt;/code&gt; option. This allows a collection of tags to be set on a post that will replace all of its existing tags:&lt;/p&gt;
&lt;div class="highlight  "&gt;&lt;div class="scroller"&gt;&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td class="line-numbers"&gt;&lt;pre&gt;1
2
3
4
5
6
7
8
9
&lt;strong&gt;10&lt;/strong&gt;
11
12
13
14
15
16
17
18
19
&lt;strong&gt;20&lt;/strong&gt;
21
22
23
24
25
26
&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;class PostResource &amp;lt; JSONAPI::Resource
  attribute :id
  attribute :title
  attribute :body
  attribute :subject

  has_one :author, class_name: 'Person'
  has_one :section
  has_many :tags, acts_as_set: true
  has_many :comments

  def subject
    @object.title
  end

  def self.updateable(keys, context)
    super(keys - [:author, :subject])
  end

  def self.createable(keys, context)
    super(keys - [:subject])
  end

  filters :title, :author
  filter :id
end
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Also note that the above resource has a computed attribute called &lt;code&gt;subject&lt;/code&gt;. This is simply the title of the post, and is not createable or updateable.&lt;/p&gt;

&lt;p&gt;A resource also controls which filters its corresponding &lt;code&gt;ResourceController&lt;/code&gt; will support. The &lt;code&gt;Resource&lt;/code&gt; class provides basic search capabilities, but if you need more control you can implement a &lt;code&gt;find&lt;/code&gt; method on your resource.&lt;/p&gt;
&lt;h4&gt;ResourceSerializer&lt;/h4&gt;
&lt;p&gt;A &lt;code&gt;ResourceSerializer&lt;/code&gt; can serialize a resource into a JSON:API compliant hash, which can then be converted to JSON. &lt;code&gt;ResourceSerializer&lt;/code&gt; has a &lt;code&gt;serialize&lt;/code&gt; method that takes a resource instance to serialize, and optional &lt;code&gt;fields&lt;/code&gt;, &lt;code&gt;includes&lt;/code&gt;, and &lt;code&gt;context&lt;/code&gt; parameters.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;
&lt;div class="highlight  "&gt;&lt;div class="scroller"&gt;&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td class="line-numbers"&gt;&lt;pre&gt;1
2
&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;post = Post.find(1)
JSONAPI::ResourceSerializer.new.serialize(PostResource.new(post))
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;This returns a hash like this:&lt;/p&gt;
&lt;div class="highlight  "&gt;&lt;div class="scroller"&gt;&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td class="line-numbers"&gt;&lt;pre&gt;1
2
3
4
5
6
7
8
9
&lt;strong&gt;10&lt;/strong&gt;
11
12
13
&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;{
  posts: [{
    id: 1,
    title: 'New post',
    body: 'A body!!!',
    links: {
      section: nil,
      author: 1,
      tags: [1,2,3],
      comments: [1,2]
    }
  }]
}
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;You can also provide some options and filter the &lt;code&gt;fields&lt;/code&gt; and &lt;code&gt;include&lt;/code&gt; related records. &lt;code&gt;include&lt;/code&gt; takes an array of related resources to serialize, and &lt;code&gt;fields&lt;/code&gt; takes a hash of resource types to an array of attributes. For example:&lt;/p&gt;
&lt;div class="highlight  "&gt;&lt;div class="scroller"&gt;&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td class="line-numbers"&gt;&lt;pre&gt;1
2
3
4
5
6
7
&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;post = Post.find(1)
JSONAPI::ResourceSerializer.new.serialize(PostResource.new(post),
  ['comments','author','comments.tags','author.posts'],
  {people: [:id, :email, :comments],
   posts: [:id, :title, :author],
   tags: [:name],
   comments: [:id, :body, :post]})
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;This outputs:&lt;/p&gt;
&lt;div class="highlight  "&gt;&lt;div class="scroller"&gt;&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td class="line-numbers"&gt;&lt;pre&gt;1
2
3
4
5
6
7
8
9
&lt;strong&gt;10&lt;/strong&gt;
11
12
13
14
15
16
17
18
19
&lt;strong&gt;20&lt;/strong&gt;
21
22
&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;{
  :posts=&amp;gt;[
    {:id=&amp;gt;1,
     :title=&amp;gt;&amp;quot;New post&amp;quot;,
     :links=&amp;gt;{:author=&amp;gt;1}}
    ],
    :linked=&amp;gt;{
      :posts=&amp;gt;[
        {:id=&amp;gt;2, :title=&amp;gt;&amp;quot;JR solves your serialization woes!&amp;quot;, :links=&amp;gt;{:author=&amp;gt;1}}
      ],
      :people=&amp;gt;[
        {:id=&amp;gt;1, :email=&amp;gt;&amp;quot;joe@xyz.fake&amp;quot;, :links=&amp;gt;{:comments=&amp;gt;[1]}}
      ],
      :tags=&amp;gt;[
        {:name=&amp;gt;&amp;quot;whiny&amp;quot;}, {:name=&amp;gt;&amp;quot;short&amp;quot;}, {:name=&amp;gt;&amp;quot;happy&amp;quot;}
      ],
      :comments=&amp;gt;[
        {:id=&amp;gt;1, :body=&amp;gt;&amp;quot;what a dumb post&amp;quot;, :links=&amp;gt;{:post=&amp;gt;1}},
        {:id=&amp;gt;2, :body=&amp;gt;&amp;quot;i liked it&amp;quot;, :links=&amp;gt;{:post=&amp;gt;1}}
      ]
    }
}
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Note that multilevel includes can be specified with a dot notation, like &lt;code&gt;&amp;#39;author.posts&amp;#39;&lt;/code&gt;. In addition, you can control the fields for each resource type.&lt;/p&gt;
&lt;h4&gt;ResourceController&lt;/h4&gt;
&lt;p&gt;The &lt;code&gt;ResourceController&lt;/code&gt; class provides &lt;code&gt;index&lt;/code&gt;, &lt;code&gt;show&lt;/code&gt;, &lt;code&gt;create&lt;/code&gt;, &lt;code&gt;update&lt;/code&gt;, &lt;code&gt;delete&lt;/code&gt;, &lt;code&gt;show_association&lt;/code&gt;, &lt;code&gt;create_association&lt;/code&gt;, and &lt;code&gt;destroy_association&lt;/code&gt; methods that function based on the resource definition matching the controller name. The easiest way to use &lt;code&gt;ResourceController&lt;/code&gt; is to derive your &lt;code&gt;ApplicationController&lt;/code&gt; from it, and in turn derive specific controllers from your &lt;code&gt;ApplicationController&lt;/code&gt;. There is no need for any methods to exist in your individual controllers unless you need to alter the default behavior.&lt;/p&gt;
&lt;div class="highlight  "&gt;&lt;div class="scroller"&gt;&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td class="line-numbers"&gt;&lt;pre&gt;1
2
3
4
5
&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;class ApplicationController &amp;lt; JSONAPI::ResourceController
end

class ContactsController &amp;lt; ApplicationController
end
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;The &lt;code&gt;ResourceController&lt;/code&gt; translates the &lt;code&gt;includes&lt;/code&gt; and &lt;code&gt;fields&lt;/code&gt; parameters from the JSON:API specified style into the internal structures used by the &lt;code&gt;ResourceSerializer&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;For example, the following request will get all the contacts with their included phone numbers:&lt;/p&gt;
&lt;div class="highlight  "&gt;&lt;div class="scroller"&gt;&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td class="line-numbers"&gt;&lt;pre&gt;1
&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;http://localhost:3000/contacts?include=phone_numbers&amp;amp;fields[contacts]=name_first,name_last&amp;amp;fields[phone_numbers]=number
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;The contact records will only contain the first and last names and the phone number will just contain the number.&lt;/p&gt;

&lt;p&gt;Of course, you don&amp;#39;t need to use &lt;code&gt;ResourceController&lt;/code&gt; if your needs are different.&lt;/p&gt;
&lt;h4&gt;Routing&lt;/h4&gt;
&lt;p&gt;JR has a couple of helper methods available to assist you with setting up routes.&lt;/p&gt;
&lt;h5&gt;jsonapi_resources&lt;/h5&gt;
&lt;p&gt;Like &lt;code&gt;resources&lt;/code&gt; in ActionDispatch, &lt;code&gt;jsonapi_resources&lt;/code&gt; provides resourceful routes mapping between HTTP verbs and URLs and controller actions. This will also setup mappings for relationship URLs for a resource&amp;#39;s associations. For example:&lt;/p&gt;
&lt;div class="highlight  "&gt;&lt;div class="scroller"&gt;&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td class="line-numbers"&gt;&lt;pre&gt;1
2
3
4
5
6
&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;require 'jsonapi/routing_ext'

Peeps::Application.routes.draw do
  jsonapi_resources :contacts
  jsonapi_resources :phone_numbers
end
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;This generates the following routes:&lt;/p&gt;
&lt;div class="highlight  "&gt;&lt;div class="scroller"&gt;&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td class="line-numbers"&gt;&lt;pre&gt;1
2
3
4
5
6
7
8
9
&lt;strong&gt;10&lt;/strong&gt;
11
12
13
14
15
16
17
18
19
&lt;strong&gt;20&lt;/strong&gt;
21
22
23
&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;                     Prefix Verb   URI Pattern                                               Controller#Action
contact_links_phone_numbers GET    /contacts/:contact_id/links/phone_numbers(.:format)       contacts#show_association {:association=&amp;gt;&amp;quot;phone_numbers&amp;quot;}
                            POST   /contacts/:contact_id/links/phone_numbers(.:format)       contacts#create_association {:association=&amp;gt;&amp;quot;phone_numbers&amp;quot;}
                            DELETE /contacts/:contact_id/links/phone_numbers/:keys(.:format) contacts#destroy_association {:association=&amp;gt;&amp;quot;phone_numbers&amp;quot;}
                   contacts GET    /contacts(.:format)                                       contacts#index
                            POST   /contacts(.:format)                                       contacts#create
                new_contact GET    /contacts/new(.:format)                                   contacts#new
               edit_contact GET    /contacts/:id/edit(.:format)                              contacts#edit
                    contact GET    /contacts/:id(.:format)                                   contacts#show
                            PATCH  /contacts/:id(.:format)                                   contacts#update
                            PUT    /contacts/:id(.:format)                                   contacts#update
                            DELETE /contacts/:id(.:format)                                   contacts#destroy
 phone_number_links_contact GET    /phone_numbers/:phone_number_id/links/contact(.:format)   phone_numbers#show_association {:association=&amp;gt;&amp;quot;contact&amp;quot;}
                            POST   /phone_numbers/:phone_number_id/links/contact(.:format)   phone_numbers#create_association {:association=&amp;gt;&amp;quot;contact&amp;quot;}
                            DELETE /phone_numbers/:phone_number_id/links/contact(.:format)   phone_numbers#destroy_association {:association=&amp;gt;&amp;quot;contact&amp;quot;}
              phone_numbers GET    /phone_numbers(.:format)                                  phone_numbers#index
                            POST   /phone_numbers(.:format)                                  phone_numbers#create
           new_phone_number GET    /phone_numbers/new(.:format)                              phone_numbers#new
          edit_phone_number GET    /phone_numbers/:id/edit(.:format)                         phone_numbers#edit
               phone_number GET    /phone_numbers/:id(.:format)                              phone_numbers#show
                            PATCH  /phone_numbers/:id(.:format)                              phone_numbers#update
                            PUT    /phone_numbers/:id(.:format)                              phone_numbers#update
                            DELETE /phone_numbers/:id(.:format)                              phone_numbers#destroy
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Use &lt;code&gt;jsonapi_resource&lt;/code&gt; for singleton resources that can be looked up without an id.&lt;/p&gt;

&lt;p&gt;You can control the relationship routes by passing a block into &lt;code&gt;jsonapi_resources&lt;/code&gt; or &lt;code&gt;jsonapi_resource&lt;/code&gt;. An empty block
will not create any relationship routes.&lt;/p&gt;

&lt;p&gt;You can add individual relationship routes with &lt;code&gt;jsonapi_links&lt;/code&gt;. For example:&lt;/p&gt;
&lt;div class="highlight  "&gt;&lt;div class="scroller"&gt;&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td class="line-numbers"&gt;&lt;pre&gt;1
2
3
4
&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;      jsonapi_resources :posts, except: [:destroy] do
        jsonapi_link :author, except: [:destroy]
        jsonapi_links :tags, only: [:show, :create]
      end
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;This will create relationship routes for &lt;code&gt;author&lt;/code&gt; (&lt;code&gt;show&lt;/code&gt; and &lt;code&gt;create&lt;/code&gt;, but not &lt;code&gt;destroy&lt;/code&gt;) and for &lt;code&gt;tags&lt;/code&gt; (again &lt;code&gt;show&lt;/code&gt; and &lt;code&gt;create&lt;/code&gt;, but not &lt;code&gt;destroy&lt;/code&gt;).&lt;/p&gt;
&lt;h2&gt;Getting started&lt;/h2&gt;
&lt;p&gt;We&amp;#39;ve shared a simple contact manager app created with JR called &lt;a href="https://github.com/cerebris/peeps"&gt;Peeps&lt;/a&gt;, which you can pull down and play with (some &lt;code&gt;curl&lt;/code&gt; examples are provided). It also contains instructions for how to recreate the app if you want to see just what&amp;#39;s involved. Hint - it&amp;#39;s not much.&lt;/p&gt;
&lt;h2&gt;Status and Next Steps&lt;/h2&gt;
&lt;p&gt;So is JSONAPI::Resources complete? In a word, no. It is functional, but it is missing plenty of features. The biggest, as far as I see them, are pagination, sorting, and support for PATCH operations. Also not yet implemented are the top level &lt;code&gt;meta&lt;/code&gt; and &lt;code&gt;links&lt;/code&gt; objects. I plan to add these over time and would love community support to make and keep JR as compliant with JSON:API as possible.&lt;/p&gt;

&lt;p&gt;In very basic testing I have found JSONAPI::Resources to be anywhere from 20% to 50% faster than the equivalent operation using version 0.8.1 of ActiveModel Serializers and 5% to 20% faster than the 0.9.0alpha master branch. Of course, there&amp;#39;s probably some speed that can still be extracted from both projects.&lt;/p&gt;

&lt;p&gt;I hope you find JSONAPI::Resources useful for building your own APIs. I&amp;#39;d appreciate your comments as well as your contributions.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Of Satellites and Rovers</title>
    <link rel="alternate" href="http://www.cerebris.com/blog/2014/01/14/of-satellites-and-rovers/"/>
    <id>http://www.cerebris.com/blog/2014/01/14/of-satellites-and-rovers/</id>
    <published>2014-01-14T00:00:00Z</published>
    <updated>2014-01-14T00:00:00Z</updated>
    <author>
      <name>Dan Gebhardt</name>
    </author>
    <summary type="html">&lt;p&gt;&lt;em&gt;A few months ago &lt;a href="/blog/2013/08/08/the-development-drawbacks-of-javascript-web-applications/"&gt;I responded to some well publicized criticisms of client-side JavaScript web applications with some counterpoints&lt;/a&gt;. I promised a followup post to help clarify architecture decisions for web applications, and here it finally is…&lt;/em&gt;&lt;/p&gt;

&lt;hr&gt;

</summary>
    <content type="html">&lt;p&gt;&lt;em&gt;A few months ago &lt;a href="/blog/2013/08/08/the-development-drawbacks-of-javascript-web-applications/"&gt;I responded to some well publicized criticisms of client-side JavaScript web applications with some counterpoints&lt;/a&gt;. I promised a followup post to help clarify architecture decisions for web applications, and here it finally is…&lt;/em&gt;&lt;/p&gt;

&lt;hr&gt;

&lt;p&gt;When deciding whether to develop a traditional web app that generates HTML on the server or a client-side &lt;a href="/blog/2013/07/31/single-page-applications/"&gt;JavaScript web app&lt;/a&gt;, it&amp;#39;s easy to focus on questions such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Which language can I use to write the bulk of my application?&lt;/li&gt;
&lt;li&gt;Which approach is faster to load initially?&lt;/li&gt;
&lt;li&gt;Which approach is faster to respond to subsequent actions?&lt;/li&gt;
&lt;li&gt;Which requires the fewest architectural layers?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These questions have fairly quantifiable answers, and one factor may be so important for your application that it overrides all others. However, when this is not the case, you may end up feeling like your architectural decisions are going to involve a lot of unpleasant trade-offs.&lt;/p&gt;
&lt;h2&gt;A Thought Experiment&lt;/h2&gt;
&lt;p&gt;If you&amp;#39;re racked with indecision, consider this: should your app be a &lt;strong&gt;communications satellite&lt;/strong&gt; or a &lt;strong&gt;Mars rover&lt;/strong&gt;?&lt;/p&gt;

&lt;p&gt;&lt;img src="/images/blog/2014/01/14/satellite.png" alt="Satellite" style="float: right; width: 250px; height: 250px;" /&gt;&lt;/p&gt;

&lt;p&gt;A communications satellite, placed in close orbit around the Earth, acts as a relay for transmitting data between two points on the planet. The satellite does not need to understand the data: it relies on the transmitter to package up content that the receiver needs.&lt;/p&gt;

&lt;p&gt;Similarly, a traditional web app relies on the server to generate HTML content, which is sent directly to the browser when requested. Once it reaches the browser, content is presented to the user with little manipulation. Every interaction with the application requires a round trip to the server. The browser becomes a relatively dumb but efficient intermediary.&lt;/p&gt;

&lt;p&gt;&lt;img src="/images/blog/2014/01/14/rover.png" alt="Rover" style="float: left; width: 250px; height: 250px;" /&gt;&lt;/p&gt;

&lt;p&gt;On the other hand, a rover is imbued with artificial intelligence. It needs to be able to navigate remote landscapes, react to unexpected obstacles in real time, and communicate findings back to mission control. It should be able to survive communication problems while still interacting with its environment. A rover is more complex and autonomous than a satellite, so it needs to be particularly well tested before launch.&lt;/p&gt;

&lt;p&gt;Just as a rover receives instructions from home and then uses them to interact with its landscape, a JavaScript web app receives raw data and needs to be able to make sense of it. It interacts directly with a user through the browser, without the need to involve &amp;quot;mission control&amp;quot; in real-time micro-decisions. Instead, it communicates in short bursts that contain exactly what it needs and what it&amp;#39;s found. It must maintain its own state and have rules defining how it should respond to state changes.&lt;/p&gt;
&lt;h2&gt;Futurama&lt;/h2&gt;
&lt;p&gt;If you&amp;#39;re still on the fence, try to look beyond the present. I consider these to be safe predictions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Processors and browsers will become more performant.&lt;/li&gt;
&lt;li&gt;Applications will be able to target evergreen browsers as they become the norm.&lt;/li&gt;
&lt;li&gt;Improvements to JavaScript will make it more modular, capable and easier to code.&lt;/li&gt;
&lt;li&gt;JavaScript frameworks will mature. Client-side data libraries will become more sophisticated and will better handle caching, transactions, undo / redo stacks and synchronization.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;10…9…8…&lt;/h2&gt;
&lt;p&gt;In short, if interactivity is important for your app, then launch its intelligence and its sensors as close to users as possible by building a client-side web app.
&lt;a href="http://emberjs.com/"&gt;Ember.js&lt;/a&gt; is particularly good at building complex, autonomous and interactive web apps, and it&amp;#39;s only getting better.&lt;/p&gt;

&lt;p&gt;On the other hand, if your site is fairly static and you simply want to broadcast content to users, a traditional server-driven architecture may be right for your app.&lt;/p&gt;

&lt;p&gt;Either way, it&amp;#39;s worth pausing to consider this decision carefully, because a change in your approach will be both time consuming and costly.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>The "Development Drawbacks" of JavaScript Web Applications</title>
    <link rel="alternate" href="http://www.cerebris.com/blog/2013/08/08/the-development-drawbacks-of-javascript-web-applications/"/>
    <id>http://www.cerebris.com/blog/2013/08/08/the-development-drawbacks-of-javascript-web-applications/</id>
    <published>2013-08-08T00:00:00Z</published>
    <updated>2013-08-08T00:00:00Z</updated>
    <author>
      <name>Dan Gebhardt</name>
    </author>
    <summary type="html">&lt;p&gt;With the advent of client-side application frameworks like &lt;a href="http://emberjs.com/"&gt;Ember&lt;/a&gt;, &lt;a href="http://angularjs.org/"&gt;Angular&lt;/a&gt;, and &lt;a href="http://backbonejs.org/"&gt;Backbone&lt;/a&gt;, there is a growing split in the web development community. A number of developers have dug in their heels against moving substantial application logic into JavaScript...&lt;/p&gt;</summary>
    <content type="html">&lt;p&gt;With the advent of client-side application frameworks like &lt;a href="http://emberjs.com/"&gt;Ember&lt;/a&gt;, &lt;a href="http://angularjs.org/"&gt;Angular&lt;/a&gt;, and &lt;a href="http://backbonejs.org/"&gt;Backbone&lt;/a&gt;, there is a growing split in the web development community. A number of developers have dug in their heels against moving substantial application logic into JavaScript, and would prefer that servers continue to render as much HTML as possible. In the &lt;a href="http://weblog.rubyonrails.org/2013/6/25/Rails-4-0-final/"&gt;release notes for Rails 4&lt;/a&gt;, David Heinemeier Hansson declared that &amp;quot;a big focus has been on making it dead simple to build modern web applications that are screaming fast without needing to go the client-side JS/JSON server route&amp;quot;. He went on to describe one of the new features, Turbolinks, as able to &amp;quot;essentially turn your app into a single-page javascript application in terms of speed, but with none of the developmental drawbacks&amp;quot;.&lt;/p&gt;

&lt;p&gt;I&amp;#39;d like to take a look at some of these perceived drawbacks and offer some counterpoints.&lt;/p&gt;
&lt;h2&gt;Language preference&lt;/h2&gt;
&lt;p&gt;&lt;img src="/images/blog/2013/08/08/language.png" alt="Language Preference" style="float: right" /&gt;&lt;/p&gt;

&lt;p&gt;Of course, we&amp;#39;ve only got one realistic language choice in the browser: JavaScript.
If you prefer Ruby (or Python or Java or C#) over JavaScript, you may favor keeping
as much of your application on the server as possible based on &amp;quot;developer happiness&amp;quot;.&lt;/p&gt;

&lt;p&gt;I agree that&amp;#39;s an important metric, but let&amp;#39;s face it: JavaScript simply can&amp;#39;t be
avoided when writing modern web applications. Instead of sprinkling jQuery snippets
throughout your application in an effort to make it more &amp;quot;dynamic&amp;quot;, you&amp;#39;ll be much
better off if you fully understand and embrace the JavaScript language.&lt;/p&gt;

&lt;p&gt;Thanks to the efforts of &lt;a href="http://www.ecma-international.org/memento/TC39.htm"&gt;TC39&lt;/a&gt;,
JavaScript is actively being improved. You may be pleasantly surprised by
&lt;a href="http://tc39wiki.calculist.org/es6/"&gt;some of the features coming in ES6&lt;/a&gt;, the next
version of JavaScript. If you really can&amp;#39;t stomach curly braces, give
&lt;a href="http://coffeescript.org/"&gt;CoffeeScript&lt;/a&gt; a try. I should add that, in my consulting
experience, I&amp;#39;ve noticed a trend towards front or back end specialization, especially
on larger teams. If you strongly favor one or the other, you may not need to
&amp;quot;wear all the hats&amp;quot; on a project.&lt;/p&gt;
&lt;h2&gt;Complexity&lt;/h2&gt;
&lt;p&gt;&lt;img src="/images/blog/2013/08/08/complexity.png" alt="Complexity" style="float: right" /&gt;&lt;/p&gt;

&lt;p&gt;It&amp;#39;s often argued that writing a client-side application paired with a backend API is substantially more complex than an equivalent server-rendered application. While that &lt;em&gt;may&lt;/em&gt; be true in launching a minimum viable product, any time-to-launch advantages will probably dissipate as your service matures. In his &lt;a href="http://mir.aculo.us/2013/02/26/client-side-mvc-is-not-a-silver-bullet/"&gt;criticism of client-side MVC&lt;/a&gt;, Thomas Fuchs claims that &amp;quot;what you end up with is building a layer cake that doesn’t add any value and slows down development.&amp;quot;&lt;/p&gt;

&lt;p&gt;I&amp;#39;ve found the opposite to be true: a strongly dilineated architecture benefits applications in the short and long run. By developing your front and back ends simultaneously, you can virtually guarantee that your service will have a useful and robust API, even at v1. And with an API as a firewall between front and back end code you&amp;#39;ll gain discipline that will clarify architectural decisions and leave you with very little duplication of functionality across your stack.&lt;/p&gt;
&lt;h2&gt;Time to Load&lt;/h2&gt;
&lt;p&gt;&lt;img src="/images/blog/2013/08/08/waiting.png" alt="Time to Load" style="float: right" /&gt;&lt;/p&gt;

&lt;p&gt;An oft-cited problem with client-side applications is the time to download and initialize on page load. The total size of many JavaScript applications, including framework code, is typically the size of one or two JPEGs, and often is less than the total JavaScript downloaded on traditional web pages once all the miscellaneous plugins are added up. That&amp;#39;s not to say that this is a non-issue: client-side applications typically don&amp;#39;t display &lt;em&gt;anything&lt;/em&gt; to users until they&amp;#39;ve been fully downloaded and initialized.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;What&amp;#39;s the answer?&lt;/em&gt; Start by delivering your assets as quickly as possible with a CDN. Consider splitting up larger applications into modules that can be progressively loaded as needed. This is possible in Ember, for instance, now that the router supports asynchronous loading of routes.&lt;/p&gt;
&lt;h2&gt;SEO&lt;/h2&gt;
&lt;p&gt;&lt;img src="/images/blog/2013/08/08/seo.png" alt="SEO" style="float: right" /&gt;&lt;/p&gt;

&lt;p&gt;Although search crawlers don&amp;#39;t yet automatically process JavaScript web applications, it&amp;#39;s actually not that difficult to ensure that your public facing content will be searchable. Google provides &lt;a href="https://developers.google.com/webmasters/ajax-crawling/docs/specification"&gt;a spec for making dynamically created content visible to crawlers&lt;/a&gt;, which Alex MacCaw discusses in his post &lt;a href="http://blog.alexmaccaw.com/seo-in-js-web-apps"&gt;SEO in JS Web Apps&lt;/a&gt;. Also check out &lt;a href="http://alexferreira.github.io/seojs/"&gt;SeoJs&lt;/a&gt;, which relies on &lt;a href="http://phantomjs.org/"&gt;PhantomJS&lt;/a&gt; to crawl your dynamic site and provide static indexable content to search spiders.&lt;/p&gt;
&lt;h2&gt;Primitive Browser Compability&lt;/h2&gt;
&lt;p&gt;&lt;img src="/images/blog/2013/08/08/primitive.png" alt="Primitive browser" style="float: right; padding-bottom: 20px;" /&gt;&lt;/p&gt;

&lt;p&gt;This criticism is obvious: if you want your site to work without JavaScript, you&amp;#39;ll need to create a version that is not entirely dependent upon JavaScript. The only way to make this happen is with redundant development of a simplified static site.&lt;/p&gt;

&lt;p&gt;Of course, a large majority of server-rendered sites are also heavily dependent on JavaScript and face similar challenges to work with scriptless browsers. But then again, it&amp;#39;s become so rare and undesirable to disable JavaScript that &lt;a href="https://bugzilla.mozilla.org/show_bug.cgi?id=873709"&gt;the option has been obfuscated in the upcoming v23 of Firefox&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Accessibility&lt;/h2&gt;
&lt;p&gt;&lt;img src="/images/blog/2013/08/08/accessibility.png" alt="Accessibility" style="float: right" /&gt;&lt;/p&gt;

&lt;p&gt;While some screen readers don&amp;#39;t work with JavaScript generated content, Apple&amp;#39;s &lt;a href="http://www.apple.com/accessibility/osx/voiceover/"&gt;VoiceOver&lt;/a&gt; does a pretty decent job regardless of where the markup was created. You can try it out in OS X simply by pressing ⌘ + F5 in your browser.&lt;/p&gt;

&lt;p&gt;Going further, the W3C&amp;#39;s &lt;a href="http://www.w3.org/WAI/intro/aria.php"&gt;WAI-ARIA&lt;/a&gt; spec aims to make dynamic content more accessible to people with disabilities. By adding custom &lt;code&gt;role&lt;/code&gt; and &lt;code&gt;aria-*&lt;/code&gt; attributes to elements, combined with semantic structure, you can provide guidance to improve how content is presented by VoiceOver and other sophisticated screen readers.&lt;/p&gt;
&lt;h2&gt;Similar Appearance&lt;/h2&gt;
&lt;p&gt;&lt;img src="/images/blog/2013/08/08/similarity.png" alt="Similar appearance" style="float: right; padding-bottom: 20px;" /&gt;&lt;/p&gt;

&lt;p&gt;Another charge that Thomas Fuchs levels is that &amp;quot;if you use something like Ember
(which we didn’t), it’s even worse as all applications using it practically look
the same (many people choose using Twitter’s Bootstrap library, for example)&amp;quot;.&lt;/p&gt;

&lt;p&gt;I&amp;#39;m not sure where this originated, but it is not unlike claiming that all Rails
applications look the same. As a frequent user of and contributor to Ember, I can
assure Thomas (and everyone else) that Ember applications are in no way tied to
a particular style or user experience. Peruse popular Ember apps like
&lt;a href="http://www.discourse.org/"&gt;Discourse&lt;/a&gt;, &lt;a href="https://www.yapp.us/"&gt;Yapp&lt;/a&gt;,
&lt;a href="http://www.zendesk.com/"&gt;Zendesk&lt;/a&gt;, and
&lt;a href="https://squareup.com/"&gt;Square&lt;/a&gt; to see for yourself.&lt;/p&gt;

&lt;hr&gt;

&lt;p&gt;I realize that this post may seem a bit defensive, but I think it&amp;#39;s important to
not let claims go unchecked. I&amp;#39;ve personally been working with
&lt;a href="http://emberjs.com/"&gt;Ember.js&lt;/a&gt; for the past 20 months and couldn&amp;#39;t be happier
with my choice &lt;em&gt;for the applications I&amp;#39;ve been developing&lt;/em&gt;. While some aspects
of development have been more challenging, I think the pros far outweigh the
cons for many types of applications.&lt;/p&gt;

&lt;p&gt;Stay tuned for a post that can help clarify this decision &lt;em&gt;for your application&lt;/em&gt;...&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>"Single Page Applications"</title>
    <link rel="alternate" href="http://www.cerebris.com/blog/2013/07/31/single-page-applications/"/>
    <id>http://www.cerebris.com/blog/2013/07/31/single-page-applications/</id>
    <published>2013-07-31T00:00:00Z</published>
    <updated>2013-07-31T00:00:00Z</updated>
    <author>
      <name>Dan Gebhardt</name>
    </author>
    <summary type="html">&lt;p&gt;I no longer use the term "Single Page Application".&lt;/p&gt;

&lt;p&gt;The term is quite server-centric, which made a lot of sense &lt;a href="http://en.wikipedia.org/wiki/Single-page_application"&gt;when it was coined
in 2005&lt;/a&gt;. However, with
the introduction of &lt;a href="https://developer.mozilla.org/en-US/docs/Web/Guide/DOM/Manipulating_the_browser_history"&gt;pushState and replaceState in HTML5&lt;/a&gt;,
applications can now directly manipulate...&lt;/p&gt;</summary>
    <content type="html">&lt;p&gt;I no longer use the term &amp;quot;Single Page Application&amp;quot;.&lt;/p&gt;

&lt;p&gt;The term is quite server-centric, which made a lot of sense &lt;a href="http://en.wikipedia.org/wiki/Single-page_application"&gt;when it was coined
in 2005&lt;/a&gt;. However, with
the introduction of &lt;a href="https://developer.mozilla.org/en-US/docs/Web/Guide/DOM/Manipulating_the_browser_history"&gt;pushState and replaceState in HTML5&lt;/a&gt;,
applications can now directly manipulate the browser&amp;#39;s history and visibly
change the URL. It&amp;#39;s hard to argue that an application exists on a &amp;quot;single page&amp;quot;
when it can navigate to multiple URLs, all of which can be bookmarked or opened
in new tabs, and can reconstitute their state with a browser refresh. Certainly
this doesn&amp;#39;t fit any &lt;em&gt;user&amp;#39;s&lt;/em&gt; definition of a &amp;quot;page&amp;quot;.&lt;/p&gt;

&lt;p&gt;Terminology is important. Instead of Single Page Application, I now say
&amp;quot;JavaScript Web Application&amp;quot;. Perhaps a bit boring, but undeniably accurate :)&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Understanding Ember.Object</title>
    <link rel="alternate" href="http://www.cerebris.com/blog/2012/03/06/understanding-ember-object/"/>
    <id>http://www.cerebris.com/blog/2012/03/06/understanding-ember-object/</id>
    <published>2012-03-06T00:00:00Z</published>
    <updated>2012-03-06T00:00:00Z</updated>
    <author>
      <name>Dan Gebhardt</name>
    </author>
    <summary type="html">&lt;p&gt;Almost every object in &lt;a href="http://emberjs.com"&gt;Ember.js&lt;/a&gt; is derived from a common
object: &lt;strong&gt;Ember.Object&lt;/strong&gt;. This object is used as the basis for views,
controllers, models, and even the application itself.&lt;/p&gt;

&lt;p&gt;This simple architectural decision is responsible for much of the consistency...&lt;/p&gt;</summary>
    <content type="html">&lt;p&gt;Almost every object in &lt;a href="http://emberjs.com"&gt;Ember.js&lt;/a&gt; is derived from a common
object: &lt;strong&gt;Ember.Object&lt;/strong&gt;. This object is used as the basis for views,
controllers, models, and even the application itself.&lt;/p&gt;

&lt;p&gt;This simple architectural decision is responsible for much of the consistency
across Ember. Because every object has been derived from the same core object,
they all share some core capabilities. Every Ember object can observe the
properties of other objects, bind their properties to the properties of other
objects, specify and update computed properties, and much more.&lt;/p&gt;

&lt;p&gt;As you&amp;#39;ll see in this post, it&amp;#39;s easy to get started with Ember.Object, but also
easy to overlook some of its capabilities. A better understanding of
Ember.Object will help you understand the architecture of Ember itself and
enable you to improve the architecture of your own application.&lt;/p&gt;
&lt;h2&gt;Creating objects&lt;/h2&gt;
&lt;p&gt;It&amp;#39;s almost as simple to create a new Ember.Object as a plain Javascript object:&lt;/p&gt;
&lt;div class="highlight javascript "&gt;&lt;div class="scroller"&gt;&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td class="line-numbers"&gt;&lt;pre&gt;1
2
3
4
5
6
7
&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="keyword"&gt;var&lt;/span&gt; emberObject = Ember.Object.create({
  &lt;span class="key"&gt;greeting&lt;/span&gt;: &lt;span class="string"&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;span class="content"&gt;hello&lt;/span&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
});

&lt;span class="keyword"&gt;var&lt;/span&gt; jsObject = {
  &lt;span class="key"&gt;greeting&lt;/span&gt;: &lt;span class="string"&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;span class="content"&gt;hello&lt;/span&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
};
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;The object literal that is optionally passed to &lt;code&gt;Ember.Object.create()&lt;/code&gt; defines
properties directly on the instantiated object, not unlike the vanilla object.
However, upon inspection in your console, you can see there&amp;#39;s quite a bit more
going on behind the scenes of the Ember object:&lt;/p&gt;

&lt;p&gt;&lt;img src="/images/blog/2012/03/06/ember_object_vs_js_object.png" alt="Ember.Object vs POJO"&gt;&lt;/p&gt;

&lt;p&gt;It would take a long tour of the Ember source to explore all the properties of 
even such a simple Ember object. Needless to say, it&amp;#39;s all required for Ember to 
enable bindings, observers, and more. Although it looks like quite a bit of 
overhead, the complexity of the Ember object is contained almost entirely in its 
prototype (&lt;code&gt;Ember.Object.prototype&lt;/code&gt;) and not within the object instance.&lt;/p&gt;
&lt;h2&gt;Extending classes&lt;/h2&gt;
&lt;p&gt;To go beyond vanilla Ember objects, you can extend &lt;code&gt;Ember.Object&lt;/code&gt; or any of its 
descendents to create your own classes:&lt;/p&gt;
&lt;div class="highlight javascript "&gt;&lt;div class="scroller"&gt;&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td class="line-numbers"&gt;&lt;pre&gt;1
2
3
4
5
6
7
8
9
&lt;strong&gt;10&lt;/strong&gt;
11
&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="keyword"&gt;var&lt;/span&gt; Person = Ember.Object.extend({
  &lt;span class="key"&gt;species&lt;/span&gt;: &lt;span class="string"&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;span class="content"&gt;homo sapiens&lt;/span&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
});

&lt;span class="keyword"&gt;var&lt;/span&gt; Man = Person.extend({
  &lt;span class="key"&gt;gender&lt;/span&gt;: &lt;span class="string"&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;span class="content"&gt;male&lt;/span&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
});

&lt;span class="keyword"&gt;var&lt;/span&gt; Woman = Person.extend({
  &lt;span class="key"&gt;gender&lt;/span&gt;: &lt;span class="string"&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;span class="content"&gt;female&lt;/span&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
});
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;em&gt;Important: the object literal that is passed as an argument to &lt;code&gt;extend()&lt;/code&gt;
defines properties for the *&lt;/em&gt;prototype** of objects that will be instantiated by
the class.*&lt;/p&gt;

&lt;p&gt;Now, let&amp;#39;s instantiate a person with &lt;code&gt;create()&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight javascript "&gt;&lt;div class="scroller"&gt;&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td class="line-numbers"&gt;&lt;pre&gt;1
2
3
&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="keyword"&gt;var&lt;/span&gt; joe = Man.create({
  &lt;span class="key"&gt;name&lt;/span&gt;: &lt;span class="string"&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;span class="content"&gt;Joe&lt;/span&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
});
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;em&gt;Important: remember that the object literal passed to &lt;code&gt;create()&lt;/code&gt; defines
properties of the *&lt;/em&gt;instantiated object** (not its prototype).*&lt;/p&gt;

&lt;p&gt;And let&amp;#39;s inspect our new person:&lt;/p&gt;
&lt;div class="highlight javascript "&gt;&lt;div class="scroller"&gt;&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td class="line-numbers"&gt;&lt;pre&gt;1
2
3
4
5
6
7
8
9
&lt;strong&gt;10&lt;/strong&gt;
&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;console.log( joe.get(&lt;span class="string"&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;span class="content"&gt;name&lt;/span&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;) );               &lt;span class="comment"&gt;// &amp;quot;Joe&amp;quot;&lt;/span&gt;
console.log( joe.hasOwnProperty(&lt;span class="string"&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;span class="content"&gt;name&lt;/span&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;) );    &lt;span class="comment"&gt;// true&lt;/span&gt;
console.log( joe.get(&lt;span class="string"&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;span class="content"&gt;gender&lt;/span&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;) );             &lt;span class="comment"&gt;// &amp;quot;male&amp;quot;&lt;/span&gt;
console.log( joe.hasOwnProperty(&lt;span class="string"&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;span class="content"&gt;gender&lt;/span&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;) );  &lt;span class="comment"&gt;// false&lt;/span&gt;
console.log( joe.get(&lt;span class="string"&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;span class="content"&gt;species&lt;/span&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;) );            &lt;span class="comment"&gt;// &amp;quot;homo sapiens&amp;quot;&lt;/span&gt;
console.log( joe.hasOwnProperty(&lt;span class="string"&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;span class="content"&gt;species&lt;/span&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;) ); &lt;span class="comment"&gt;// false&lt;/span&gt;

console.log( Man.prototype.isPrototypeOf(joe) );          &lt;span class="comment"&gt;// true&lt;/span&gt;
console.log( Person.prototype.isPrototypeOf(joe) );       &lt;span class="comment"&gt;// true&lt;/span&gt;
console.log( Ember.Object.prototype.isPrototypeOf(joe) ); &lt;span class="comment"&gt;// true&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;As you can see, the prototype chain for &lt;code&gt;joe&lt;/code&gt; includes &lt;code&gt;Man.prototype&lt;/code&gt;,
&lt;code&gt;Person.prototype&lt;/code&gt;, and &lt;code&gt;Ember.Object.prototype&lt;/code&gt;. Our person can correctly
evaluate his name (defined directly on the instance), gender (defined on
&lt;code&gt;Man.prototype&lt;/code&gt;), and species (defined on &lt;code&gt;Person.prototype&lt;/code&gt;). What a smart guy!&lt;/p&gt;
&lt;h2&gt;Initialization (and a common mistake!)&lt;/h2&gt;
&lt;p&gt;One of the most common mistakes for beginners to Ember is to think they&amp;#39;re
passing properties to an instance instead of a prototype. For example:&lt;/p&gt;
&lt;div class="highlight javascript "&gt;&lt;div class="scroller"&gt;&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td class="line-numbers"&gt;&lt;pre&gt;1
2
3
4
5
6
7
8
9
&lt;strong&gt;10&lt;/strong&gt;
11
12
13
&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="keyword"&gt;var&lt;/span&gt; Person = Ember.Object.extend({
  &lt;span class="key"&gt;chromosomes&lt;/span&gt;: [&lt;span class="string"&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;span class="content"&gt;x&lt;/span&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;] &lt;span class="comment"&gt;// CAREFUL !!!!!&lt;/span&gt;
});

&lt;span class="keyword"&gt;var&lt;/span&gt; joe = Person.create();
joe.get(&lt;span class="string"&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;span class="content"&gt;chromosomes&lt;/span&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;).push(&lt;span class="string"&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;span class="content"&gt;y&lt;/span&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;);

&lt;span class="keyword"&gt;var&lt;/span&gt; jane = Person.create();
jane.get(&lt;span class="string"&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;span class="content"&gt;chromosomes&lt;/span&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;).push(&lt;span class="string"&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;span class="content"&gt;x&lt;/span&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;);

&lt;span class="comment"&gt;// Joe and Jane are all mixed up?!?!?!?!&lt;/span&gt;
console.log( joe.get(&lt;span class="string"&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;span class="content"&gt;chromosomes&lt;/span&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;) );  &lt;span class="comment"&gt;// x, y, x&lt;/span&gt;
console.log( jane.get(&lt;span class="string"&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;span class="content"&gt;chromosomes&lt;/span&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;) ); &lt;span class="comment"&gt;// x, y, x&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Why did this chromosomal mutation happen? The problem started when we added an
array to our prototype when defining the &lt;code&gt;Person&lt;/code&gt; class. This array was then
shared with each object instantiated from &lt;code&gt;Person&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;How should we have handled this?&lt;/p&gt;
&lt;div class="highlight javascript "&gt;&lt;div class="scroller"&gt;&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td class="line-numbers"&gt;&lt;pre&gt;1
2
3
4
5
6
7
8
9
&lt;strong&gt;10&lt;/strong&gt;
11
12
13
14
15
16
17
&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="keyword"&gt;var&lt;/span&gt; Person = Ember.Object.extend({
  &lt;span class="key"&gt;chromosomes&lt;/span&gt;: &lt;span class="predefined-constant"&gt;null&lt;/span&gt;,
  &lt;span class="function"&gt;init&lt;/span&gt;: &lt;span class="keyword"&gt;function&lt;/span&gt;() {
    &lt;span class="local-variable"&gt;this&lt;/span&gt;._super();
    &lt;span class="local-variable"&gt;this&lt;/span&gt;.set(&lt;span class="string"&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;span class="content"&gt;chromosomes&lt;/span&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, [&lt;span class="string"&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;span class="content"&gt;x&lt;/span&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;]); &lt;span class="comment"&gt;// everyone gets at least one X chromosome&lt;/span&gt;
  }
});

&lt;span class="keyword"&gt;var&lt;/span&gt; joe = Person.create();
joe.get(&lt;span class="string"&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;span class="content"&gt;chromosomes&lt;/span&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;).push(&lt;span class="string"&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;span class="content"&gt;y&lt;/span&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;);  &lt;span class="comment"&gt;// men also get a Y chromosome&lt;/span&gt;

&lt;span class="keyword"&gt;var&lt;/span&gt; jane = Person.create();
jane.get(&lt;span class="string"&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;span class="content"&gt;chromosomes&lt;/span&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;).push(&lt;span class="string"&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;span class="content"&gt;x&lt;/span&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;); &lt;span class="comment"&gt;// women get another X chromosome&lt;/span&gt;

&lt;span class="comment"&gt;// Hurray - everyone gets their own chromosomes!&lt;/span&gt;
console.log( joe.get(&lt;span class="string"&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;span class="content"&gt;chromosomes&lt;/span&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;) );  &lt;span class="comment"&gt;// x, y&lt;/span&gt;
console.log( jane.get(&lt;span class="string"&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;span class="content"&gt;chromosomes&lt;/span&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;) ); &lt;span class="comment"&gt;// x, x&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;When declaring objects or arrays in your classes, you&amp;#39;ll typically want to
initialize them along with each instance in the &lt;code&gt;init()&lt;/code&gt; function. In this way,
each of your objects will receive its own unique instances of objects and
arrays. Also remember to call &lt;code&gt;this._super()&lt;/code&gt; from within &lt;code&gt;init()&lt;/code&gt; so that
&lt;code&gt;init()&lt;/code&gt; will be called all the way up the prototype chain.&lt;/p&gt;

&lt;p&gt;Of course, there&amp;#39;s nothing wrong with keeping objects or arrays directly in your
prototypes if they are meant to remain constant across instances. In fact, one
common pattern is to keep a default setting in the prototype that&amp;#39;s then
duplicated for each instance in &lt;code&gt;init()&lt;/code&gt;. These kinds of patterns are easy to
implement once you realize how objects are created and initialized.&lt;/p&gt;

&lt;p&gt;Want to play more with inheritance and initialization? I&amp;#39;ve extended this
example on &lt;a href="http://jsfiddle.net/dgeb/h3PmN/"&gt;jsFiddle&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Reopening objects and classes&lt;/h2&gt;
&lt;p&gt;You can easily add properties to Ember classes after they&amp;#39;ve been defined using
&lt;code&gt;reopen()&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight javascript "&gt;&lt;div class="scroller"&gt;&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td class="line-numbers"&gt;&lt;pre&gt;1
2
3
4
5
6
7
8
&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="keyword"&gt;var&lt;/span&gt; Person = Ember.Object.extend({
  &lt;span class="key"&gt;firstName&lt;/span&gt;: &lt;span class="predefined-constant"&gt;null&lt;/span&gt;,
  &lt;span class="key"&gt;lastName&lt;/span&gt;:  &lt;span class="predefined-constant"&gt;null&lt;/span&gt;
});

Person.reopen({
  &lt;span class="key"&gt;middleName&lt;/span&gt;: &lt;span class="predefined-constant"&gt;null&lt;/span&gt;
});
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Specifically, &lt;code&gt;reopen()&lt;/code&gt; modifies the prototype that will be used for objects
instantiated by a class.&lt;/p&gt;

&lt;p&gt;If you want to add properties directly to a class, use &lt;code&gt;reopenClass()&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight javascript "&gt;&lt;div class="scroller"&gt;&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td class="line-numbers"&gt;&lt;pre&gt;1
2
3
4
5
6
7
8
9
&lt;strong&gt;10&lt;/strong&gt;
11
12
&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="keyword"&gt;var&lt;/span&gt; Person = Ember.Object.extend({
  &lt;span class="key"&gt;firstName&lt;/span&gt;: &lt;span class="predefined-constant"&gt;null&lt;/span&gt;,
  &lt;span class="key"&gt;lastName&lt;/span&gt;:  &lt;span class="predefined-constant"&gt;null&lt;/span&gt;
});

Person.reopenClass({
  &lt;span class="function"&gt;makeBaby&lt;/span&gt;: &lt;span class="keyword"&gt;function&lt;/span&gt;(attributes) {
    &lt;span class="keyword"&gt;return&lt;/span&gt; Person.create(attributes);
  }
});

&lt;span class="keyword"&gt;var&lt;/span&gt; huey = Person.makeBaby({&lt;span class="key"&gt;firstName&lt;/span&gt;: &lt;span class="string"&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;span class="content"&gt;Baby&lt;/span&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class="key"&gt;lastName&lt;/span&gt;: &lt;span class="string"&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;span class="content"&gt;Huey&lt;/span&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;});
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;One useful pattern is to define class methods for finding and/or creating
objects.&lt;/p&gt;
&lt;h2&gt;Mixing in concerns&lt;/h2&gt;
&lt;p&gt;While extending classes in a hierarchical fashion often works well, there is a
tendency to end up with classes such as &lt;code&gt;MaleLeftHandedPetOwnersOfPoodles&lt;/code&gt;.
Trying to munge together a bunch of separate concerns in a single class can get
messy. Ember&amp;#39;s answer to this problem is &lt;code&gt;Ember.Mixin&lt;/code&gt;. Here it is in action:&lt;/p&gt;
&lt;div class="highlight javascript "&gt;&lt;div class="scroller"&gt;&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td class="line-numbers"&gt;&lt;pre&gt;1
2
3
4
5
6
7
8
9
&lt;strong&gt;10&lt;/strong&gt;
11
12
13
14
15
16
17
18
19
&lt;strong&gt;20&lt;/strong&gt;
21
22
23
24
25
26
27
28
29
&lt;strong&gt;30&lt;/strong&gt;
31
32
33
34
35
36
&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="keyword"&gt;var&lt;/span&gt; Pet = Em.Object.extend({
  &lt;span class="key"&gt;name&lt;/span&gt;: &lt;span class="predefined-constant"&gt;null&lt;/span&gt;
});

&lt;span class="keyword"&gt;var&lt;/span&gt; PetOwner = Ember.Mixin.create({
  &lt;span class="key"&gt;pet&lt;/span&gt;: &lt;span class="predefined-constant"&gt;null&lt;/span&gt;,

  &lt;span class="function"&gt;init&lt;/span&gt;: &lt;span class="keyword"&gt;function&lt;/span&gt;() {
    &lt;span class="local-variable"&gt;this&lt;/span&gt;._super();
    &lt;span class="local-variable"&gt;this&lt;/span&gt;.set(&lt;span class="string"&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;span class="content"&gt;pet&lt;/span&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, Pet.create({}));
  }
});

&lt;span class="keyword"&gt;var&lt;/span&gt; Male = Ember.Mixin.create({
  &lt;span class="key"&gt;chromosomes&lt;/span&gt;: &lt;span class="predefined-constant"&gt;null&lt;/span&gt;,

  &lt;span class="function"&gt;init&lt;/span&gt;: &lt;span class="keyword"&gt;function&lt;/span&gt;() {
    &lt;span class="local-variable"&gt;this&lt;/span&gt;._super();
    &lt;span class="local-variable"&gt;this&lt;/span&gt;.set(&lt;span class="string"&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;span class="content"&gt;chromosomes&lt;/span&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, [&lt;span class="string"&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;span class="content"&gt;x&lt;/span&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class="string"&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;span class="content"&gt;y&lt;/span&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;]);
  }
});

&lt;span class="keyword"&gt;var&lt;/span&gt; joe = Ember.Object.create(PetOwner, Male, {
  &lt;span class="key"&gt;age&lt;/span&gt;:  &lt;span class="integer"&gt;25&lt;/span&gt;,
  &lt;span class="key"&gt;name&lt;/span&gt;: &lt;span class="string"&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;span class="content"&gt;Joe&lt;/span&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;,

  &lt;span class="function"&gt;init&lt;/span&gt;: &lt;span class="keyword"&gt;function&lt;/span&gt;() {
    &lt;span class="local-variable"&gt;this&lt;/span&gt;._super();
    &lt;span class="local-variable"&gt;this&lt;/span&gt;.get(&lt;span class="string"&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;span class="content"&gt;pet&lt;/span&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;).set(&lt;span class="string"&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;span class="content"&gt;name&lt;/span&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class="string"&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;span class="content"&gt;Fifi&lt;/span&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;);
  }
});

console.log( joe.get(&lt;span class="string"&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;span class="content"&gt;name&lt;/span&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;) );            &lt;span class="comment"&gt;// Joe&lt;/span&gt;
console.log( joe.get(&lt;span class="string"&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;span class="content"&gt;age&lt;/span&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;) );             &lt;span class="comment"&gt;// 25&lt;/span&gt;
console.log( joe.get(&lt;span class="string"&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;span class="content"&gt;chromosomes&lt;/span&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;) );     &lt;span class="comment"&gt;// x,y&lt;/span&gt;
console.log( joe.get(&lt;span class="string"&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;span class="content"&gt;pet.name&lt;/span&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;) );        &lt;span class="comment"&gt;// Fifi&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;In this example, we&amp;#39;re merging a number of separate concerns in a single object.
Joe is both a &lt;code&gt;PetOwner&lt;/code&gt; and a &lt;code&gt;Male&lt;/code&gt;, and has other traits such as an &lt;code&gt;age&lt;/code&gt; and
&lt;code&gt;name&lt;/code&gt;. He not only has a &lt;code&gt;pet&lt;/code&gt;, but that pet even has a &lt;code&gt;name&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The separate concerns are each represented by an &lt;code&gt;Ember.Mixin&lt;/code&gt;. The &lt;code&gt;joe&lt;/code&gt; object
is created as a merger of the &lt;code&gt;PetOwner&lt;/code&gt; and &lt;code&gt;Male&lt;/code&gt; mixins, as well an object
literal that represents instance properties. Mixins get initialized in the order
in which they are passed to &lt;code&gt;create()&lt;/code&gt;, which allows &lt;code&gt;joe&lt;/code&gt; to set his pet&amp;#39;s name
after &lt;code&gt;PetOwner&lt;/code&gt; has created that pet.&lt;/p&gt;

&lt;p&gt;Want to play more with this example? It&amp;#39;s also on
&lt;a href="http://jsfiddle.net/dgeb/gZQ95/"&gt;jsFiddle&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;But wait... there&amp;#39;s more :)&lt;/h2&gt;
&lt;p&gt;Mixins aren&amp;#39;t limited to objects that you &lt;code&gt;create()&lt;/code&gt;. They can also be used with
&lt;code&gt;extend()&lt;/code&gt;, &lt;code&gt;reopen()&lt;/code&gt;, and &lt;code&gt;reopenClass&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Furthermore, there&amp;#39;s a &lt;a href="https://github.com/emberjs/ember.js/tree/master/packages/ember-runtime/lib/mixins"&gt;suite of useful mixins&lt;/a&gt;
built right into Ember core. Do you want your object to be enumerable? Mix in
&lt;a href="https://github.com/emberjs/ember.js/blob/master/packages/ember-runtime/lib/mixins/enumerable.js"&gt;Ember.Enumerable&lt;/a&gt;.
Want to create a view that triggers an action? Extend it with
&lt;a href="https://github.com/emberjs/ember.js/blob/master/packages/ember-runtime/lib/mixins/target_action_support.js"&gt;Ember.TargetActionSupport&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I think you&amp;#39;ll find that by separating lateral concerns in mixins, and
hierarchical concerns with &lt;code&gt;extend()&lt;/code&gt;, you can build a very flexible
architecture for your Ember apps.&lt;/p&gt;

&lt;hr&gt;

&lt;p&gt;&lt;em&gt;Any questions or suggestions for further Ember posts? Please feel free to
comment below -- Dan&lt;/em&gt;&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Beginning Ember.js on Rails: Part 3</title>
    <link rel="alternate" href="http://www.cerebris.com/blog/2012/01/31/beginning-ember-js-on-rails-part-3/"/>
    <id>http://www.cerebris.com/blog/2012/01/31/beginning-ember-js-on-rails-part-3/</id>
    <published>2012-01-31T00:00:00Z</published>
    <updated>2012-01-31T00:00:00Z</updated>
    <author>
      <name>Dan Gebhardt</name>
    </author>
    <summary type="html">&lt;p&gt;&lt;em&gt;This is part of a series of posts about Ember.js. Please read &lt;a href="/blog/2012/01/20/warming-up-to-ember-js/"&gt;Warming up to Ember.js&lt;/a&gt; as well as the &lt;a href="http://emberjs.com"&gt;Ember.js home page&lt;/a&gt; if you're new to Ember.js.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;As promised in &lt;a href="/blog/2012/01/26/beginning-ember-js-on-rails-part-2/"&gt;Part 2&lt;/a&gt; of this series, this post will show how records are added, updated and removed...&lt;/p&gt;</summary>
    <content type="html">&lt;p&gt;&lt;em&gt;This is part of a series of posts about Ember.js. Please read &lt;a href="/blog/2012/01/20/warming-up-to-ember-js/"&gt;Warming up to Ember.js&lt;/a&gt; as well as the &lt;a href="http://emberjs.com"&gt;Ember.js home page&lt;/a&gt; if you&amp;#39;re new to Ember.js.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;As promised in &lt;a href="/blog/2012/01/26/beginning-ember-js-on-rails-part-2/"&gt;Part 2&lt;/a&gt; of this series, this post will show how records are added, updated and removed in our &lt;a href="https://github.com/dgeb/ember_rest_example"&gt;example app&lt;/a&gt;. This app uses our ultra-simple &lt;a href="https://github.com/cerebris/ember-rest"&gt;Ember REST&lt;/a&gt; library to communicate with a REST interface served by Rails. I&amp;#39;ll try to point out when parts of this example use the persistence library (&lt;code&gt;ember-rest.js&lt;/code&gt;) instead of core Ember (&lt;code&gt;ember.js&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Because our REST interface was completed in Part 2, let&amp;#39;s move right to the client-side code...&lt;/p&gt;
&lt;h2&gt;Creating records&lt;/h2&gt;
&lt;p&gt;We&amp;#39;ll start by extending our Ember model and views to enable creating records. As you&amp;#39;ll soon see, much of this work is applicable to editing records as well.&lt;/p&gt;
&lt;h3&gt;Extend the model&lt;/h3&gt;
&lt;p&gt;In order to serialize our model, we need to define its &lt;code&gt;resourceName&lt;/code&gt; and &lt;code&gt;resourceProperties&lt;/code&gt;. In this way, &lt;code&gt;ember-rest.js&lt;/code&gt; can send back only the data required by our REST interface:&lt;/p&gt;

&lt;div class="code-header"&gt;app/assets/javascripts/app/models/contact.js&lt;/div&gt;
&lt;div class="highlight javascript "&gt;&lt;div class="scroller"&gt;&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td class="line-numbers"&gt;&lt;pre&gt;1
2
3
4
5
6
7
8
9
&lt;strong&gt;10&lt;/strong&gt;
11
12
13
14
15
16
&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;App.Contact = Ember.Resource.extend({
  &lt;span class="key"&gt;resourceUrl&lt;/span&gt;:        &lt;span class="string"&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;span class="content"&gt;/contacts&lt;/span&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;/span&gt;,
  &lt;span class="key"&gt;resourceName&lt;/span&gt;:       &lt;span class="string"&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;span class="content"&gt;contact&lt;/span&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;/span&gt;,
  &lt;span class="key"&gt;resourceProperties&lt;/span&gt;: [&lt;span class="string"&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;span class="content"&gt;first_name&lt;/span&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;/span&gt;, &lt;span class="string"&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;span class="content"&gt;last_name&lt;/span&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;/span&gt;],

  &lt;span class="function"&gt;validate&lt;/span&gt;: &lt;span class="keyword"&gt;function&lt;/span&gt;() {
    &lt;span class="keyword"&gt;if&lt;/span&gt; (&lt;span class="local-variable"&gt;this&lt;/span&gt;.get(&lt;span class="string"&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;span class="content"&gt;first_name&lt;/span&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;/span&gt;) === &lt;span class="predefined-constant"&gt;undefined&lt;/span&gt; || &lt;span class="local-variable"&gt;this&lt;/span&gt;.get(&lt;span class="string"&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;span class="content"&gt;first_name&lt;/span&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;/span&gt;) === &lt;span class="string"&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;/span&gt; ||
        &lt;span class="local-variable"&gt;this&lt;/span&gt;.get(&lt;span class="string"&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;span class="content"&gt;last_name&lt;/span&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;/span&gt;) === &lt;span class="predefined-constant"&gt;undefined&lt;/span&gt;  || &lt;span class="local-variable"&gt;this&lt;/span&gt;.get(&lt;span class="string"&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;span class="content"&gt;last_name&lt;/span&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;/span&gt;) === &lt;span class="string"&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;/span&gt;) {
      &lt;span class="keyword"&gt;return&lt;/span&gt; &lt;span class="string"&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;span class="content"&gt;Contacts require a first and a last name.&lt;/span&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;/span&gt;;
    }
  },

  &lt;span class="key"&gt;fullName&lt;/span&gt;: Ember.computed(&lt;span class="keyword"&gt;function&lt;/span&gt;() {
    &lt;span class="keyword"&gt;return&lt;/span&gt; &lt;span class="local-variable"&gt;this&lt;/span&gt;.get(&lt;span class="string"&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;span class="content"&gt;first_name&lt;/span&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;/span&gt;) + &lt;span class="string"&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;span class="content"&gt; &lt;/span&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;/span&gt; + &lt;span class="local-variable"&gt;this&lt;/span&gt;.get(&lt;span class="string"&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;span class="content"&gt;last_name&lt;/span&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;/span&gt;);
  }).property(&lt;span class="string"&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;span class="content"&gt;first_name&lt;/span&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;/span&gt;, &lt;span class="string"&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;span class="content"&gt;last_name&lt;/span&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;/span&gt;)
});
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;The optional &lt;code&gt;validate()&lt;/code&gt; method will be called by &lt;code&gt;ember-rest.js&lt;/code&gt; when saving records. Returning an error string or object will prevent saving an invalid record. &lt;em&gt;And yes, those validations might look cleaner in CoffeeScript ;)&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;Extend the listing view&lt;/h3&gt;
&lt;p&gt;Our listing view needs to allow contacts to be added. Let&amp;#39;s modify its template first:&lt;/p&gt;

&lt;div class="code-header"&gt;app/assets/javascripts/app/templates/contacts/list.handlebars&lt;/div&gt;
&lt;div class="highlight handlebars "&gt;&lt;div class="scroller"&gt;&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td class="line-numbers"&gt;&lt;pre&gt;1
2
3
4
5
6
7
8
9
&lt;strong&gt;10&lt;/strong&gt;
11
12
13
14
15
16
17
18
19
&lt;strong&gt;20&lt;/strong&gt;
21
22
23
24
&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="tag"&gt;&amp;lt;table&amp;gt;&lt;/span&gt;
  &lt;span class="tag"&gt;&amp;lt;thead&amp;gt;&lt;/span&gt;
    &lt;span class="tag"&gt;&amp;lt;tr&amp;gt;&lt;/span&gt;
      &lt;span class="tag"&gt;&amp;lt;th&amp;gt;&lt;/span&gt;ID&lt;span class="tag"&gt;&amp;lt;/th&amp;gt;&lt;/span&gt;
      &lt;span class="tag"&gt;&amp;lt;th&amp;gt;&lt;/span&gt;Name&lt;span class="tag"&gt;&amp;lt;/th&amp;gt;&lt;/span&gt;
    &lt;span class="tag"&gt;&amp;lt;/tr&amp;gt;&lt;/span&gt;
  &lt;span class="tag"&gt;&amp;lt;/thead&amp;gt;&lt;/span&gt;
  &lt;span class="tag"&gt;&amp;lt;tbody&amp;gt;&lt;/span&gt;
  &lt;span class="inline"&gt;&lt;span class="inline-delimiter"&gt;{{#&lt;/span&gt;&lt;span class="attribute-name"&gt;each&lt;/span&gt; &lt;span class="attribute-name"&gt;contacts&lt;/span&gt;&lt;span class="inline-delimiter"&gt;}}&lt;/span&gt;&lt;/span&gt;
    &lt;span class="inline"&gt;&lt;span class="inline-delimiter"&gt;{{&lt;/span&gt;&lt;span class="attribute-name"&gt;view&lt;/span&gt; &lt;span class="attribute-name"&gt;App.ShowContactView&lt;/span&gt; &lt;span class="attribute-name"&gt;contactBinding&lt;/span&gt;=&lt;span class="string"&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;span class="content"&gt;this&lt;/span&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span class="inline-delimiter"&gt;}}&lt;/span&gt;&lt;/span&gt;
  &lt;span class="inline"&gt;&lt;span class="inline-delimiter"&gt;{{/&lt;/span&gt;&lt;span class="attribute-name"&gt;each&lt;/span&gt;&lt;span class="inline-delimiter"&gt;}}&lt;/span&gt;&lt;/span&gt;
  &lt;span class="inline"&gt;&lt;span class="inline-delimiter"&gt;{{#&lt;/span&gt;&lt;span class="attribute-name"&gt;if&lt;/span&gt; &lt;span class="attribute-name"&gt;isNewVisible&lt;/span&gt;&lt;span class="inline-delimiter"&gt;}}&lt;/span&gt;&lt;/span&gt;
    &lt;span class="tag"&gt;&amp;lt;tr&amp;gt;&lt;/span&gt;
      &lt;span class="tag"&gt;&amp;lt;td&amp;gt;&lt;/span&gt;*&lt;span class="tag"&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
      &lt;span class="tag"&gt;&amp;lt;td&amp;gt;&lt;/span&gt;
        &lt;span class="inline"&gt;&lt;span class="inline-delimiter"&gt;{{&lt;/span&gt;&lt;span class="attribute-name"&gt;view&lt;/span&gt; &lt;span class="attribute-name"&gt;App.NewContactView&lt;/span&gt;&lt;span class="inline-delimiter"&gt;}}&lt;/span&gt;&lt;/span&gt;
      &lt;span class="tag"&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
    &lt;span class="tag"&gt;&amp;lt;/tr&amp;gt;&lt;/span&gt;
  &lt;span class="inline"&gt;&lt;span class="inline-delimiter"&gt;{{/&lt;/span&gt;&lt;span class="attribute-name"&gt;if&lt;/span&gt;&lt;span class="inline-delimiter"&gt;}}&lt;/span&gt;&lt;/span&gt;
  &lt;span class="tag"&gt;&amp;lt;/tbody&amp;gt;&lt;/span&gt;
&lt;span class="tag"&gt;&amp;lt;/table&amp;gt;&lt;/span&gt;
&lt;span class="tag"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="attribute-name"&gt;class&lt;/span&gt;=&lt;span class="string"&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;span class="content"&gt;commands&lt;/span&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span class="tag"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="tag"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="attribute-name"&gt;href&lt;/span&gt;=&lt;span class="string"&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;span class="content"&gt;#&lt;/span&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class="inline"&gt;&lt;span class="inline-delimiter"&gt;{{&lt;/span&gt;&lt;span class="attribute-name"&gt;action&lt;/span&gt; &lt;span class="error"&gt;&amp;quot;&lt;/span&gt;&lt;span class="attribute-name"&gt;showNew&lt;/span&gt;&lt;span class="error"&gt;&amp;quot;&lt;/span&gt;&lt;span class="inline-delimiter"&gt;}}&lt;/span&gt;&lt;/span&gt;&lt;span class="tag"&gt;&amp;gt;&lt;/span&gt;New Contact&lt;span class="tag"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
&lt;span class="tag"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Notice the &amp;quot;New Contact&amp;quot; link at the bottom. We&amp;#39;re using the &lt;code&gt;{{action}}&lt;/code&gt; helper to delegate its &lt;code&gt;click&lt;/code&gt; event (the default for &lt;code&gt;action&lt;/code&gt;) to the &lt;code&gt;showNew()&lt;/code&gt; handler on the listing&amp;#39;s view class:&lt;/p&gt;

&lt;div class="code-header"&gt;app/assets/javascripts/app/views/contacts/list.js&lt;/div&gt;
&lt;div class="highlight javascript "&gt;&lt;div class="scroller"&gt;&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td class="line-numbers"&gt;&lt;pre&gt;1
2
3
4
5
6
7
8
9
&lt;strong&gt;10&lt;/strong&gt;
11
12
&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;App.ListContactsView = Ember.View.extend({
  &lt;span class="key"&gt;templateName&lt;/span&gt;:    &lt;span class="string"&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;span class="content"&gt;app/templates/contacts/list&lt;/span&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;/span&gt;,
  &lt;span class="key"&gt;contactsBinding&lt;/span&gt;: &lt;span class="string"&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;span class="content"&gt;App.contactsController&lt;/span&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;/span&gt;,

  &lt;span class="function"&gt;showNew&lt;/span&gt;: &lt;span class="keyword"&gt;function&lt;/span&gt;() {
    &lt;span class="local-variable"&gt;this&lt;/span&gt;.set(&lt;span class="string"&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;span class="content"&gt;isNewVisible&lt;/span&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;/span&gt;, &lt;span class="predefined-constant"&gt;true&lt;/span&gt;);
  },

  &lt;span class="function"&gt;hideNew&lt;/span&gt;: &lt;span class="keyword"&gt;function&lt;/span&gt;() {
    &lt;span class="local-variable"&gt;this&lt;/span&gt;.set(&lt;span class="string"&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;span class="content"&gt;isNewVisible&lt;/span&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;/span&gt;, &lt;span class="predefined-constant"&gt;false&lt;/span&gt;);
  }
});
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;In turn, the view class sets its &lt;code&gt;isNewVisible&lt;/code&gt; property to true. By using &lt;code&gt;set()&lt;/code&gt;, Ember&amp;#39;s bindings will trigger a change in the above template. &lt;code&gt;{{#if isNewVisible}}&lt;/code&gt; will now be true, so the extra row will be displayed in our listing.&lt;/p&gt;
&lt;h3&gt;Create a view for new contacts&lt;/h3&gt;
&lt;p&gt;As you can see in the listing&amp;#39;s template, a &lt;code&gt;NewContactView&lt;/code&gt; will be created within the new row in our listing:&lt;/p&gt;

&lt;div class="code-header"&gt;app/assets/javascripts/app/views/contacts/new.js&lt;/div&gt;
&lt;div class="highlight javascript "&gt;&lt;div class="scroller"&gt;&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td class="line-numbers"&gt;&lt;pre&gt;1
2
3
4
5
6
7
8
9
&lt;strong&gt;10&lt;/strong&gt;
11
12
13
14
15
16
17
18
19
&lt;strong&gt;20&lt;/strong&gt;
21
22
23
24
25
26
27
28
29
&lt;strong&gt;30&lt;/strong&gt;
31
32
33
34
&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;App.NewContactView = Ember.View.extend({
  &lt;span class="key"&gt;tagName&lt;/span&gt;:      &lt;span class="string"&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;span class="content"&gt;form&lt;/span&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;/span&gt;,
  &lt;span class="key"&gt;templateName&lt;/span&gt;: &lt;span class="string"&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;span class="content"&gt;app/templates/contacts/edit&lt;/span&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;/span&gt;,

  &lt;span class="function"&gt;init&lt;/span&gt;: &lt;span class="keyword"&gt;function&lt;/span&gt;() {
    &lt;span class="local-variable"&gt;this&lt;/span&gt;._super();
    &lt;span class="local-variable"&gt;this&lt;/span&gt;.set(&lt;span class="string"&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;span class="content"&gt;contact&lt;/span&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, App.Contact.create());
  },

  &lt;span class="function"&gt;didInsertElement&lt;/span&gt;: &lt;span class="keyword"&gt;function&lt;/span&gt;() {
    &lt;span class="local-variable"&gt;this&lt;/span&gt;._super();
    &lt;span class="local-variable"&gt;this&lt;/span&gt;.&lt;span class="predefined"&gt;$&lt;/span&gt;(&lt;span class="string"&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;span class="content"&gt;input:first&lt;/span&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;/span&gt;).focus();
  },

  &lt;span class="function"&gt;cancelForm&lt;/span&gt;: &lt;span class="keyword"&gt;function&lt;/span&gt;() {
    &lt;span class="local-variable"&gt;this&lt;/span&gt;.get(&lt;span class="string"&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;span class="content"&gt;parentView&lt;/span&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;).hideNew();
  },

  &lt;span class="function"&gt;submit&lt;/span&gt;: &lt;span class="keyword"&gt;function&lt;/span&gt;(event) {
    &lt;span class="keyword"&gt;var&lt;/span&gt; self = &lt;span class="local-variable"&gt;this&lt;/span&gt;;
    &lt;span class="keyword"&gt;var&lt;/span&gt; contact = &lt;span class="local-variable"&gt;this&lt;/span&gt;.get(&lt;span class="string"&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;span class="content"&gt;contact&lt;/span&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;);

    event.preventDefault();

    contact.saveResource()
      .fail( &lt;span class="keyword"&gt;function&lt;/span&gt;(e) {
        App.displayError(e);
      })
      .done(&lt;span class="keyword"&gt;function&lt;/span&gt;() {
        App.contactsController.pushObject(contact);
        self.get(&lt;span class="string"&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;span class="content"&gt;parentView&lt;/span&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;).hideNew();
      });
  }
});
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;em&gt;There&amp;#39;s a lot going on here!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;First of all, this view&amp;#39;s &lt;code&gt;tagName&lt;/code&gt; will make it a &lt;code&gt;form&lt;/code&gt; instead of the default &lt;code&gt;div&lt;/code&gt;. Next are a couple methods overridden from the standard &lt;code&gt;Ember.View&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;init()&lt;/strong&gt; - This is called to set up a view, but before it gets added to the DOM. It&amp;#39;s a good place to create a new contact object and associate it with our view. This object will be referenced in templates associated with our view.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;didInsertElement()&lt;/strong&gt; - This is called immediately after our element gets inserted in the DOM. It&amp;#39;s a good place for us to set focus to the initial input element on our form.&lt;/p&gt;

&lt;p&gt;There are also a couple custom methods:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;cancelForm()&lt;/strong&gt; - hides this form in our parent view (see &lt;code&gt;hideNew()&lt;/code&gt; in the listing view above).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;submit()&lt;/strong&gt; - Ember will automatically set up event listeners for views when you add methods from a standard list (currently &lt;a href="https://github.com/emberjs/ember.js/blob/master/packages/ember-views/lib/system/event_dispatcher.js#L36-73"&gt;here&lt;/a&gt;). In this case, we&amp;#39;ll be listening for our form&amp;#39;s &lt;code&gt;submit()&lt;/code&gt; event.&lt;/p&gt;

&lt;p&gt;Within the &lt;code&gt;submit()&lt;/code&gt; handler, we&amp;#39;ll attempt to create our contact with the &lt;code&gt;saveResource()&lt;/code&gt; method defined in &lt;code&gt;ember-rest.js&lt;/code&gt;. The jQuery deferred methods &lt;code&gt;fail()&lt;/code&gt; and &lt;code&gt;done()&lt;/code&gt; will handle failure and success. Failure could come from either a client-side validation problem in our model, a problem communicating with the server, or an error returned from our Rails controller. On success, the new contact will be pushed into our controller&amp;#39;s collection. &lt;em&gt;There&amp;#39;s no need to refresh our views - Ember will just add a new entry to our listing!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Let&amp;#39;s check out the template for this view:&lt;/p&gt;

&lt;div class="code-header"&gt;app/assets/javascripts/app/templates/contacts/edit.handlebars&lt;/div&gt;
&lt;div class="highlight handlebars "&gt;&lt;div class="scroller"&gt;&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td class="line-numbers"&gt;&lt;pre&gt;1
2
3
4
5
6
7
8
&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="inline"&gt;&lt;span class="inline-delimiter"&gt;{{#&lt;/span&gt;&lt;span class="attribute-name"&gt;with&lt;/span&gt; &lt;span class="attribute-name"&gt;contact&lt;/span&gt;&lt;span class="inline-delimiter"&gt;}}&lt;/span&gt;&lt;/span&gt;
  &lt;span class="inline"&gt;&lt;span class="inline-delimiter"&gt;{{&lt;/span&gt;&lt;span class="attribute-name"&gt;view&lt;/span&gt; &lt;span class="attribute-name"&gt;Ember.TextField&lt;/span&gt; &lt;span class="attribute-name"&gt;valueBinding&lt;/span&gt;=&lt;span class="string"&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;span class="content"&gt;first_name&lt;/span&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class="attribute-name"&gt;placeholder&lt;/span&gt;=&lt;span class="string"&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;span class="content"&gt;First name&lt;/span&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span class="inline-delimiter"&gt;}}&lt;/span&gt;&lt;/span&gt;
  &lt;span class="inline"&gt;&lt;span class="inline-delimiter"&gt;{{&lt;/span&gt;&lt;span class="attribute-name"&gt;view&lt;/span&gt; &lt;span class="attribute-name"&gt;Ember.TextField&lt;/span&gt; &lt;span class="attribute-name"&gt;valueBinding&lt;/span&gt;=&lt;span class="string"&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;span class="content"&gt;last_name&lt;/span&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;  &lt;span class="attribute-name"&gt;placeholder&lt;/span&gt;=&lt;span class="string"&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;span class="content"&gt;Last name&lt;/span&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span class="inline-delimiter"&gt;}}&lt;/span&gt;&lt;/span&gt;
  &lt;span class="tag"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="attribute-name"&gt;type&lt;/span&gt;=&lt;span class="string"&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;span class="content"&gt;submit&lt;/span&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span class="tag"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="inline"&gt;&lt;span class="inline-delimiter"&gt;{{#&lt;/span&gt;&lt;span class="attribute-name"&gt;if&lt;/span&gt; &lt;span class="attribute-name"&gt;id&lt;/span&gt;&lt;span class="inline-delimiter"&gt;}}&lt;/span&gt;&lt;/span&gt;Update&lt;span class="inline"&gt;&lt;span class="inline-delimiter"&gt;{{&lt;/span&gt;&lt;span class="attribute-name"&gt;else&lt;/span&gt;&lt;span class="inline-delimiter"&gt;}}&lt;/span&gt;&lt;/span&gt;Create&lt;span class="inline"&gt;&lt;span class="inline-delimiter"&gt;{{/&lt;/span&gt;&lt;span class="attribute-name"&gt;if&lt;/span&gt;&lt;span class="inline-delimiter"&gt;}}&lt;/span&gt;&lt;/span&gt;
  &lt;span class="tag"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;span class="inline"&gt;&lt;span class="inline-delimiter"&gt;{{/&lt;/span&gt;&lt;span class="attribute-name"&gt;with&lt;/span&gt;&lt;span class="inline-delimiter"&gt;}}&lt;/span&gt;&lt;/span&gt;
&lt;span class="tag"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="attribute-name"&gt;href&lt;/span&gt;=&lt;span class="string"&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;span class="content"&gt;#&lt;/span&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class="inline"&gt;&lt;span class="inline-delimiter"&gt;{{&lt;/span&gt;&lt;span class="attribute-name"&gt;action&lt;/span&gt; &lt;span class="error"&gt;&amp;quot;&lt;/span&gt;&lt;span class="attribute-name"&gt;cancelForm&lt;/span&gt;&lt;span class="error"&gt;&amp;quot;&lt;/span&gt;&lt;span class="inline-delimiter"&gt;}}&lt;/span&gt;&lt;/span&gt;&lt;span class="tag"&gt;&amp;gt;&lt;/span&gt;Cancel&lt;span class="tag"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Perhaps you noticed that we aren&amp;#39;t applying any attributes from our form to our model before calling &lt;code&gt;saveResource()&lt;/code&gt;? We can skip this messiness because we&amp;#39;ve bound &lt;code&gt;Ember.TextField&lt;/code&gt; views to our model&amp;#39;s properties. Each view tracks focus and keyboard events to ensure that the model&amp;#39;s property stays in sync with its corresponding &lt;code&gt;input&lt;/code&gt; field.&lt;/p&gt;

&lt;p&gt;You might also notice that, to determine the submit button&amp;#39;s text, we&amp;#39;re checking the model&amp;#39;s &lt;code&gt;id&lt;/code&gt; to see if this is a new record to create or an existing one to update. In this way, we can reuse this template to handle edits.&lt;/p&gt;
&lt;h2&gt;Editing and deleting records&lt;/h2&gt;
&lt;p&gt;Editing records is very similar to adding them. The major difference is that, in order to enable changes to be saved or cancelled, we&amp;#39;re going to edit a copy of our object instead of the object itself.&lt;/p&gt;

&lt;p&gt;Because the changes needed to edit and delete records require changes in the same views, I’m going to explain them together.&lt;/p&gt;
&lt;h3&gt;Extending the show view&lt;/h3&gt;
&lt;p&gt;Let&amp;#39;s extend the template we&amp;#39;re using to display each record in our listing:&lt;/p&gt;

&lt;div class="code-header"&gt;app/assets/javascripts/app/templates/contacts/show.handlebars&lt;/div&gt;
&lt;div class="highlight handlebars "&gt;&lt;div class="scroller"&gt;&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td class="line-numbers"&gt;&lt;pre&gt;1
2
3
4
5
6
7
8
9
&lt;strong&gt;10&lt;/strong&gt;
11
12
13
14
&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="tag"&gt;&amp;lt;td&amp;gt;&lt;/span&gt;&lt;span class="inline"&gt;&lt;span class="inline-delimiter"&gt;{{&lt;/span&gt;&lt;span class="attribute-name"&gt;contact.id&lt;/span&gt;&lt;span class="inline-delimiter"&gt;}}&lt;/span&gt;&lt;/span&gt;&lt;span class="tag"&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
&lt;span class="tag"&gt;&amp;lt;td&lt;/span&gt; &lt;span class="attribute-name"&gt;class&lt;/span&gt;=&lt;span class="string"&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;span class="content"&gt;data&lt;/span&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span class="tag"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="inline"&gt;&lt;span class="inline-delimiter"&gt;{{#&lt;/span&gt;&lt;span class="attribute-name"&gt;if&lt;/span&gt; &lt;span class="attribute-name"&gt;isEditing&lt;/span&gt;&lt;span class="inline-delimiter"&gt;}}&lt;/span&gt;&lt;/span&gt;
    &lt;span class="inline"&gt;&lt;span class="inline-delimiter"&gt;{{&lt;/span&gt;&lt;span class="attribute-name"&gt;view&lt;/span&gt; &lt;span class="attribute-name"&gt;App.EditContactView&lt;/span&gt;&lt;span class="inline-delimiter"&gt;}}&lt;/span&gt;&lt;/span&gt;
  &lt;span class="inline"&gt;&lt;span class="inline-delimiter"&gt;{{&lt;/span&gt;&lt;span class="attribute-name"&gt;else&lt;/span&gt;&lt;span class="inline-delimiter"&gt;}}&lt;/span&gt;&lt;/span&gt;
    &lt;span class="inline"&gt;&lt;span class="inline-delimiter"&gt;{{&lt;/span&gt;&lt;span class="attribute-name"&gt;contact.fullName&lt;/span&gt;&lt;span class="inline-delimiter"&gt;}}&lt;/span&gt;&lt;/span&gt;
  &lt;span class="inline"&gt;&lt;span class="inline-delimiter"&gt;{{/&lt;/span&gt;&lt;span class="attribute-name"&gt;if&lt;/span&gt;&lt;span class="inline-delimiter"&gt;}}&lt;/span&gt;&lt;/span&gt;
  &lt;span class="tag"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="attribute-name"&gt;class&lt;/span&gt;=&lt;span class="string"&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;span class="content"&gt;commands&lt;/span&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span class="tag"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="inline"&gt;&lt;span class="inline-delimiter"&gt;{{#&lt;/span&gt;&lt;span class="attribute-name"&gt;unless&lt;/span&gt; &lt;span class="attribute-name"&gt;isEditing&lt;/span&gt;&lt;span class="inline-delimiter"&gt;}}&lt;/span&gt;&lt;/span&gt;
      &lt;span class="tag"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="attribute-name"&gt;href&lt;/span&gt;=&lt;span class="string"&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;span class="content"&gt;#&lt;/span&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class="inline"&gt;&lt;span class="inline-delimiter"&gt;{{&lt;/span&gt;&lt;span class="attribute-name"&gt;action&lt;/span&gt; &lt;span class="error"&gt;&amp;quot;&lt;/span&gt;&lt;span class="attribute-name"&gt;showEdit&lt;/span&gt;&lt;span class="error"&gt;&amp;quot;&lt;/span&gt;&lt;span class="inline-delimiter"&gt;}}&lt;/span&gt;&lt;/span&gt;&lt;span class="tag"&gt;&amp;gt;&lt;/span&gt;Edit&lt;span class="tag"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
      &lt;span class="tag"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="attribute-name"&gt;href&lt;/span&gt;=&lt;span class="string"&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;span class="content"&gt;#&lt;/span&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class="inline"&gt;&lt;span class="inline-delimiter"&gt;{{&lt;/span&gt;&lt;span class="attribute-name"&gt;action&lt;/span&gt; &lt;span class="error"&gt;&amp;quot;&lt;/span&gt;&lt;span class="attribute-name"&gt;destroyRecord&lt;/span&gt;&lt;span class="error"&gt;&amp;quot;&lt;/span&gt;&lt;span class="inline-delimiter"&gt;}}&lt;/span&gt;&lt;/span&gt;&lt;span class="tag"&gt;&amp;gt;&lt;/span&gt;Remove&lt;span class="tag"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
    &lt;span class="inline"&gt;&lt;span class="inline-delimiter"&gt;{{/&lt;/span&gt;&lt;span class="attribute-name"&gt;unless&lt;/span&gt;&lt;span class="inline-delimiter"&gt;}}&lt;/span&gt;&lt;/span&gt;
  &lt;span class="tag"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="tag"&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;You can see that we&amp;#39;re following the same pattern from our listing template to either show an &lt;code&gt;EditContactView&lt;/code&gt; when &lt;code&gt;isEditing&lt;/code&gt; is true, or &lt;code&gt;contact.fullName&lt;/code&gt; when it&amp;#39;s not. Also, when we&amp;#39;re not editing this contact, we display links to edit / remove it.&lt;/p&gt;

&lt;p&gt;Let&amp;#39;s also extend the corresponding view class:&lt;/p&gt;

&lt;div class="code-header"&gt;app/assets/javascripts/app/views/contacts/show.js&lt;/div&gt;
&lt;div class="highlight javascript "&gt;&lt;div class="scroller"&gt;&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td class="line-numbers"&gt;&lt;pre&gt;1
2
3
4
5
6
7
8
9
&lt;strong&gt;10&lt;/strong&gt;
11
12
13
14
15
16
17
18
19
&lt;strong&gt;20&lt;/strong&gt;
21
22
23
24
25
26
27
28
29
&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;App.ShowContactView = Ember.View.extend({
  &lt;span class="key"&gt;templateName&lt;/span&gt;: &lt;span class="string"&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;span class="content"&gt;app/templates/contacts/show&lt;/span&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;/span&gt;,
  &lt;span class="key"&gt;classNames&lt;/span&gt;:   [&lt;span class="string"&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;span class="content"&gt;show-contact&lt;/span&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;/span&gt;],
  &lt;span class="key"&gt;tagName&lt;/span&gt;:      &lt;span class="string"&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;span class="content"&gt;tr&lt;/span&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;/span&gt;,

  &lt;span class="function"&gt;doubleClick&lt;/span&gt;: &lt;span class="keyword"&gt;function&lt;/span&gt;() {
    &lt;span class="local-variable"&gt;this&lt;/span&gt;.showEdit();
  },

  &lt;span class="function"&gt;showEdit&lt;/span&gt;: &lt;span class="keyword"&gt;function&lt;/span&gt;() {
    &lt;span class="local-variable"&gt;this&lt;/span&gt;.set(&lt;span class="string"&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;span class="content"&gt;isEditing&lt;/span&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;/span&gt;, &lt;span class="predefined-constant"&gt;true&lt;/span&gt;);
  },

  &lt;span class="function"&gt;hideEdit&lt;/span&gt;: &lt;span class="keyword"&gt;function&lt;/span&gt;() {
    &lt;span class="local-variable"&gt;this&lt;/span&gt;.set(&lt;span class="string"&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;span class="content"&gt;isEditing&lt;/span&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;/span&gt;, &lt;span class="predefined-constant"&gt;false&lt;/span&gt;);
  },

  &lt;span class="function"&gt;destroyRecord&lt;/span&gt;: &lt;span class="keyword"&gt;function&lt;/span&gt;() {
    &lt;span class="keyword"&gt;var&lt;/span&gt; contact = &lt;span class="local-variable"&gt;this&lt;/span&gt;.get(&lt;span class="string"&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;span class="content"&gt;contact&lt;/span&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;);

    contact.destroyResource()
      .fail( &lt;span class="keyword"&gt;function&lt;/span&gt;(e) {
        App.displayError(e);
      })
      .done(&lt;span class="keyword"&gt;function&lt;/span&gt;() {
        App.contactsController.removeObject(contact);
      });
  }
});
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;The &lt;code&gt;showEdit()&lt;/code&gt; and &lt;code&gt;hideEdit()&lt;/code&gt; handlers toggle &lt;code&gt;isEditing&lt;/code&gt;, which controls whether &lt;code&gt;EditContactView&lt;/code&gt; will be shown within the template (as seen above).&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;destroyRecord()&lt;/code&gt; handler calls our model&amp;#39;s &lt;code&gt;destroyResource()&lt;/code&gt; method, defined in &lt;code&gt;ember-rest.js&lt;/code&gt;. It has &lt;code&gt;fail()&lt;/code&gt; and &lt;code&gt;done()&lt;/code&gt; deferreds, just like &lt;code&gt;saveResource()&lt;/code&gt;. On success, the record is removed from the controller&amp;#39;s collection. &lt;em&gt;As you could guess, Ember ensures that this change is reflected in the DOM immediately.&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;Extending the edit view&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;EditContactView&lt;/code&gt; is similar to &lt;code&gt;NewContactView&lt;/code&gt;, with a few exceptions:&lt;/p&gt;

&lt;div class="code-header"&gt;app/assets/javascripts/app/views/contacts/edit.js&lt;/div&gt;
&lt;div class="highlight javascript "&gt;&lt;div class="scroller"&gt;&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td class="line-numbers"&gt;&lt;pre&gt;1
2
3
4
5
6
7
8
9
&lt;strong&gt;10&lt;/strong&gt;
11
12
13
14
15
16
17
18
19
&lt;strong&gt;20&lt;/strong&gt;
21
22
23
24
25
26
27
28
29
&lt;strong&gt;30&lt;/strong&gt;
31
32
33
34
35
36
37
38
39
&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;App.EditContactView = Ember.View.extend({
  &lt;span class="key"&gt;tagName&lt;/span&gt;:      &lt;span class="string"&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;span class="content"&gt;form&lt;/span&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;/span&gt;,
  &lt;span class="key"&gt;templateName&lt;/span&gt;: &lt;span class="string"&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;span class="content"&gt;app/templates/contacts/edit&lt;/span&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;/span&gt;,

  &lt;span class="function"&gt;init&lt;/span&gt;: &lt;span class="keyword"&gt;function&lt;/span&gt;() {
    &lt;span class="local-variable"&gt;this&lt;/span&gt;._super();

    &lt;span class="comment"&gt;// Create a new contact that's a duplicate of the contact in the parentView;&lt;/span&gt;
    &lt;span class="comment"&gt;// Changes made to the duplicate won't be applied to the original unless&lt;/span&gt;
    &lt;span class="comment"&gt;// everything goes well in submitForm()&lt;/span&gt;
    &lt;span class="local-variable"&gt;this&lt;/span&gt;.set(&lt;span class="string"&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;span class="content"&gt;contact&lt;/span&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class="local-variable"&gt;this&lt;/span&gt;.get(&lt;span class="string"&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;span class="content"&gt;parentView&lt;/span&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;/span&gt;).get(&lt;span class="string"&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;span class="content"&gt;contact&lt;/span&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;/span&gt;).copy());
  },

  &lt;span class="function"&gt;didInsertElement&lt;/span&gt;: &lt;span class="keyword"&gt;function&lt;/span&gt;() {
    &lt;span class="local-variable"&gt;this&lt;/span&gt;._super();
    &lt;span class="local-variable"&gt;this&lt;/span&gt;.&lt;span class="predefined"&gt;$&lt;/span&gt;(&lt;span class="string"&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;span class="content"&gt;input:first&lt;/span&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;/span&gt;).focus();
  },

  &lt;span class="function"&gt;cancelForm&lt;/span&gt;: &lt;span class="keyword"&gt;function&lt;/span&gt;() {
    &lt;span class="local-variable"&gt;this&lt;/span&gt;.get(&lt;span class="string"&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;span class="content"&gt;parentView&lt;/span&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;).hideEdit();
  },

  &lt;span class="function"&gt;submit&lt;/span&gt;: &lt;span class="keyword"&gt;function&lt;/span&gt;(event) {
    &lt;span class="keyword"&gt;var&lt;/span&gt; self = &lt;span class="local-variable"&gt;this&lt;/span&gt;;
    &lt;span class="keyword"&gt;var&lt;/span&gt; contact = &lt;span class="local-variable"&gt;this&lt;/span&gt;.get(&lt;span class="string"&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;span class="content"&gt;contact&lt;/span&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;);

    event.preventDefault();

    contact.saveResource()
      .fail( &lt;span class="keyword"&gt;function&lt;/span&gt;(e) {
        App.displayError(e);
      })
      .done( &lt;span class="keyword"&gt;function&lt;/span&gt;() {
        &lt;span class="keyword"&gt;var&lt;/span&gt; parentView = self.get(&lt;span class="string"&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;span class="content"&gt;parentView&lt;/span&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;);
        parentView.get(&lt;span class="string"&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;span class="content"&gt;contact&lt;/span&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;).duplicateProperties(contact);
        parentView.hideEdit();
      });
  }
});
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Within &lt;code&gt;init()&lt;/code&gt;, we create a copy of the parent view&amp;#39;s contact. This allows us to make changes that can be discarded if the form is cancelled.&lt;/p&gt;

&lt;p&gt;In &lt;code&gt;submit()&lt;/code&gt;, the contact&amp;#39;s updated properties are copied back to the original after it&amp;#39;s been saved successfully. This is done using the &lt;code&gt;duplicateProperties()&lt;/code&gt; helper from &lt;code&gt;ember-rest.js&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Of course, if you&amp;#39;d prefer that edits be made directly to the original record, you could skip both of these steps.&lt;/p&gt;

&lt;p&gt;&lt;hr /&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Whew, we made it!&lt;/em&gt; I hope that this series piqued your interest enough to try Ember yourself. If you&amp;#39;ve just been reading along, try running and modifying the &lt;a href="https://github.com/dgeb/ember_rest_example"&gt;example app&lt;/a&gt; yourself.&lt;/p&gt;

&lt;p&gt;Although this is the final part of &amp;quot;Beginning Ember.js on Rails&amp;quot;, I plan to blog more about Ember. There&amp;#39;s quite a bit more to this framework than I&amp;#39;ve covered here, so please let me know if you have suggestions for future posts. If you&amp;#39;d like to stay tuned, you can follow our RSS, Twitter and Github accounts in the lower right. Thanks! - Dan&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Beginning Ember.js on Rails: Part 2</title>
    <link rel="alternate" href="http://www.cerebris.com/blog/2012/01/26/beginning-ember-js-on-rails-part-2/"/>
    <id>http://www.cerebris.com/blog/2012/01/26/beginning-ember-js-on-rails-part-2/</id>
    <published>2012-01-26T00:00:00Z</published>
    <updated>2012-01-26T00:00:00Z</updated>
    <author>
      <name>Dan Gebhardt</name>
    </author>
    <summary type="html">&lt;p&gt;&lt;em&gt;This is part of a series of posts on Ember.js. Please read
&lt;a href="/blog/2012/01/20/warming-up-to-ember-js/"&gt;Warming up to Ember.js&lt;/a&gt; as well
as the &lt;a href="http://emberjs.com"&gt;Ember.js home page&lt;/a&gt; if you're new to Ember.js.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;As promised in
&lt;a href="/blog/2012/01/24/beginning-ember-js-on-rails-part-1/"&gt;Part 1&lt;/a&gt;
of this series, this post will show how the
&lt;a href="https://github.com/dgeb/ember_rest_example"&gt;example app&lt;/a&gt; uses our ultra-simple
&lt;a href="https://github.com/cerebris/ember-rest"&gt;Ember...&lt;/a&gt;&lt;/p&gt;</summary>
    <content type="html">&lt;p&gt;&lt;em&gt;This is part of a series of posts on Ember.js. Please read
&lt;a href="/blog/2012/01/20/warming-up-to-ember-js/"&gt;Warming up to Ember.js&lt;/a&gt; as well
as the &lt;a href="http://emberjs.com"&gt;Ember.js home page&lt;/a&gt; if you&amp;#39;re new to Ember.js.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;As promised in
&lt;a href="/blog/2012/01/24/beginning-ember-js-on-rails-part-1/"&gt;Part 1&lt;/a&gt;
of this series, this post will show how the
&lt;a href="https://github.com/dgeb/ember_rest_example"&gt;example app&lt;/a&gt; uses our ultra-simple
&lt;a href="https://github.com/cerebris/ember-rest"&gt;Ember REST&lt;/a&gt; library to query a
resource&amp;#39;s REST interface to display a list of records.&lt;/p&gt;
&lt;h2&gt;Server-side Rails&lt;/h2&gt;
&lt;p&gt;Our Rails code is close to the minimum needed to serve up a RESTful JSON
interface. It was originally generated with &lt;code&gt;rails g scaffold&lt;/code&gt; and then
simplified further.&lt;/p&gt;
&lt;h3&gt;Model&lt;/h3&gt;
&lt;p&gt;The Rails model for contacts is quite basic:&lt;/p&gt;

&lt;div class="code-header"&gt;app/models/contact.rb&lt;/div&gt;
&lt;div class="highlight ruby "&gt;&lt;div class="scroller"&gt;&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td class="line-numbers"&gt;&lt;pre&gt;1
2
3
4
&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="keyword"&gt;class&lt;/span&gt; &lt;span class="class"&gt;Contact&lt;/span&gt; &amp;lt; &lt;span class="constant"&gt;ActiveRecord&lt;/span&gt;::&lt;span class="constant"&gt;Base&lt;/span&gt;
  validates &lt;span class="symbol"&gt;:first_name&lt;/span&gt;, &lt;span class="symbol"&gt;:presence&lt;/span&gt; =&amp;gt; &lt;span class="predefined-constant"&gt;true&lt;/span&gt;
  validates &lt;span class="symbol"&gt;:last_name&lt;/span&gt;, &lt;span class="symbol"&gt;:presence&lt;/span&gt; =&amp;gt; &lt;span class="predefined-constant"&gt;true&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;&lt;/div&gt;&lt;h3&gt;Controller&lt;/h3&gt;
&lt;p&gt;The controller is a simplified version of the scaffolding:&lt;/p&gt;

&lt;div class="code-header"&gt;app/controllers/contacts_controller.rb&lt;/div&gt;
&lt;div class="highlight ruby "&gt;&lt;div class="scroller"&gt;&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td class="line-numbers"&gt;&lt;pre&gt;1
2
3
4
5
6
7
8
9
&lt;strong&gt;10&lt;/strong&gt;
11
12
13
14
15
16
17
18
19
&lt;strong&gt;20&lt;/strong&gt;
21
22
23
24
25
26
27
28
29
&lt;strong&gt;30&lt;/strong&gt;
31
32
33
34
35
36
37
38
39
&lt;strong&gt;40&lt;/strong&gt;
41
42
43
44
45
46
47
48
49
&lt;strong&gt;50&lt;/strong&gt;
51
52
53
54
55
56
57
&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="keyword"&gt;class&lt;/span&gt; &lt;span class="class"&gt;ContactsController&lt;/span&gt; &amp;lt; &lt;span class="constant"&gt;ApplicationController&lt;/span&gt;
  &lt;span class="comment"&gt;# GET /contacts&lt;/span&gt;
  &lt;span class="comment"&gt;# GET /contacts.json&lt;/span&gt;
  &lt;span class="keyword"&gt;def&lt;/span&gt; &lt;span class="function"&gt;index&lt;/span&gt;
    &lt;span class="instance-variable"&gt;@contacts&lt;/span&gt; = &lt;span class="constant"&gt;Contact&lt;/span&gt;.all

    respond_to &lt;span class="keyword"&gt;do&lt;/span&gt; |format|
      format.html &lt;span class="comment"&gt;# index.html.erb&lt;/span&gt;
      format.json { render &lt;span class="key"&gt;json&lt;/span&gt;: &lt;span class="instance-variable"&gt;@contacts&lt;/span&gt; }
    &lt;span class="keyword"&gt;end&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;

  &lt;span class="comment"&gt;# GET /contacts/1.json&lt;/span&gt;
  &lt;span class="keyword"&gt;def&lt;/span&gt; &lt;span class="function"&gt;show&lt;/span&gt;
    &lt;span class="instance-variable"&gt;@contact&lt;/span&gt; = &lt;span class="constant"&gt;Contact&lt;/span&gt;.find(params[&lt;span class="symbol"&gt;:id&lt;/span&gt;])

    respond_to &lt;span class="keyword"&gt;do&lt;/span&gt; |format|
      format.json { render &lt;span class="key"&gt;json&lt;/span&gt;: &lt;span class="instance-variable"&gt;@contact&lt;/span&gt; }
    &lt;span class="keyword"&gt;end&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;

  &lt;span class="comment"&gt;# POST /contacts.json&lt;/span&gt;
  &lt;span class="keyword"&gt;def&lt;/span&gt; &lt;span class="function"&gt;create&lt;/span&gt;
    &lt;span class="instance-variable"&gt;@contact&lt;/span&gt; = &lt;span class="constant"&gt;Contact&lt;/span&gt;.new(params[&lt;span class="symbol"&gt;:contact&lt;/span&gt;])

    respond_to &lt;span class="keyword"&gt;do&lt;/span&gt; |format|
      &lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="instance-variable"&gt;@contact&lt;/span&gt;.save
        format.json { render &lt;span class="key"&gt;json&lt;/span&gt;: &lt;span class="instance-variable"&gt;@contact&lt;/span&gt;, &lt;span class="key"&gt;status&lt;/span&gt;: &lt;span class="symbol"&gt;:created&lt;/span&gt;, &lt;span class="key"&gt;location&lt;/span&gt;: &lt;span class="instance-variable"&gt;@contact&lt;/span&gt; }
      &lt;span class="keyword"&gt;else&lt;/span&gt;
        format.json { render &lt;span class="key"&gt;json&lt;/span&gt;: &lt;span class="instance-variable"&gt;@contact&lt;/span&gt;.errors, &lt;span class="key"&gt;status&lt;/span&gt;: &lt;span class="symbol"&gt;:unprocessable_entity&lt;/span&gt; }
      &lt;span class="keyword"&gt;end&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;

  &lt;span class="comment"&gt;# PUT /contacts/1.json&lt;/span&gt;
  &lt;span class="keyword"&gt;def&lt;/span&gt; &lt;span class="function"&gt;update&lt;/span&gt;
    &lt;span class="instance-variable"&gt;@contact&lt;/span&gt; = &lt;span class="constant"&gt;Contact&lt;/span&gt;.find(params[&lt;span class="symbol"&gt;:id&lt;/span&gt;])

    respond_to &lt;span class="keyword"&gt;do&lt;/span&gt; |format|
      &lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="instance-variable"&gt;@contact&lt;/span&gt;.update_attributes(params[&lt;span class="symbol"&gt;:contact&lt;/span&gt;])
        format.json { render &lt;span class="key"&gt;json&lt;/span&gt;: &lt;span class="predefined-constant"&gt;nil&lt;/span&gt;, &lt;span class="key"&gt;status&lt;/span&gt;: &lt;span class="symbol"&gt;:ok&lt;/span&gt; }
      &lt;span class="keyword"&gt;else&lt;/span&gt;
        format.json { render &lt;span class="key"&gt;json&lt;/span&gt;: &lt;span class="instance-variable"&gt;@contact&lt;/span&gt;.errors, &lt;span class="key"&gt;status&lt;/span&gt;: &lt;span class="symbol"&gt;:unprocessable_entity&lt;/span&gt; }
      &lt;span class="keyword"&gt;end&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;

  &lt;span class="comment"&gt;# DELETE /contacts/1.json&lt;/span&gt;
  &lt;span class="keyword"&gt;def&lt;/span&gt; &lt;span class="function"&gt;destroy&lt;/span&gt;
    &lt;span class="instance-variable"&gt;@contact&lt;/span&gt; = &lt;span class="constant"&gt;Contact&lt;/span&gt;.find(params[&lt;span class="symbol"&gt;:id&lt;/span&gt;])
    &lt;span class="instance-variable"&gt;@contact&lt;/span&gt;.destroy

    respond_to &lt;span class="keyword"&gt;do&lt;/span&gt; |format|
      format.json { render &lt;span class="key"&gt;json&lt;/span&gt;: &lt;span class="predefined-constant"&gt;nil&lt;/span&gt;, &lt;span class="key"&gt;status&lt;/span&gt;: &lt;span class="symbol"&gt;:ok&lt;/span&gt; }
    &lt;span class="keyword"&gt;end&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;There are a couple interesting aspects to this controller code. First of all,
the only action that responds to an html request is &lt;code&gt;index&lt;/code&gt;. I&amp;#39;ve trimmed the
others to respond only with json.&lt;/p&gt;

&lt;p&gt;Also note that the &lt;code&gt;update&lt;/code&gt; and &lt;code&gt;destroy&lt;/code&gt; actions respond to success with:&lt;/p&gt;
&lt;div class="highlight ruby "&gt;&lt;div class="scroller"&gt;&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td class="line-numbers"&gt;&lt;pre&gt;1
&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;  render &lt;span class="key"&gt;json&lt;/span&gt;: &lt;span class="predefined-constant"&gt;nil&lt;/span&gt;, &lt;span class="key"&gt;status&lt;/span&gt;: &lt;span class="symbol"&gt;:ok&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;... instead of the scaffolded default (&lt;code&gt;head :ok&lt;/code&gt;), which &lt;code&gt;jQuery.ajax()&lt;/code&gt;
interprets as an error.&lt;/p&gt;
&lt;h3&gt;Routes&lt;/h3&gt;
&lt;p&gt;As you can see, we&amp;#39;re routing root requests to our contacts controller:&lt;/p&gt;

&lt;div class="code-header"&gt;config/routes.rb&lt;/div&gt;
&lt;div class="highlight ruby "&gt;&lt;div class="scroller"&gt;&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td class="line-numbers"&gt;&lt;pre&gt;1
2
3
4
&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="constant"&gt;EmberRestExample&lt;/span&gt;::&lt;span class="constant"&gt;Application&lt;/span&gt;.routes.draw &lt;span class="keyword"&gt;do&lt;/span&gt;
  root &lt;span class="symbol"&gt;:to&lt;/span&gt; =&amp;gt; &lt;span class="string"&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;span class="content"&gt;contacts#index&lt;/span&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;/span&gt;
  resources &lt;span class="symbol"&gt;:contacts&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Let&amp;#39;s move to the client-side before we get back to our server-side views...&lt;/p&gt;
&lt;h2&gt;Client-side Ember&lt;/h2&gt;
&lt;p&gt;We&amp;#39;re now going to take a quick look at the client-side Ember model, view and
controller code needed to display a list of contacts. This code is all organized
within &lt;code&gt;app/assets/javascripts/app/&lt;/code&gt;, as discussed in
&lt;a href="/blog/2012/01/24/beginning-ember-js-on-rails-part-1/"&gt;part 1&lt;/a&gt;
of this series.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;If you&amp;#39;re following along in the
&lt;a href="https://github.com/dgeb/ember_rest_example"&gt;example code&lt;/a&gt;, note that I&amp;#39;m
leaving out a lot of the code having to do with editing records for the sake of
simplicity.&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;Application&lt;/h3&gt;
&lt;p&gt;As reviewed in the first part of this series, the application object can be
quite simple:&lt;/p&gt;

&lt;div class="code-header"&gt;app/assets/javascripts/app/app.js&lt;/div&gt;
&lt;div class="highlight javascript "&gt;&lt;div class="scroller"&gt;&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td class="line-numbers"&gt;&lt;pre&gt;1
&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;App = Ember.Application.create();
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;This object will contain all of the models, controllers and views for the
application.&lt;/p&gt;
&lt;h3&gt;Model&lt;/h3&gt;
&lt;p&gt;Let&amp;#39;s move along to the model:&lt;/p&gt;

&lt;div class="code-header"&gt;app/assets/javascripts/app/models/contact.js&lt;/div&gt;
&lt;div class="highlight javascript "&gt;&lt;div class="scroller"&gt;&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td class="line-numbers"&gt;&lt;pre&gt;1
2
3
4
5
6
7
&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;App.Contact  = Ember.Resource.extend({
  &lt;span class="key"&gt;resourceUrl&lt;/span&gt;: &lt;span class="string"&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;span class="content"&gt;/contacts&lt;/span&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;/span&gt;,

  &lt;span class="key"&gt;fullName&lt;/span&gt;: Ember.computed(&lt;span class="keyword"&gt;function&lt;/span&gt;() {
    &lt;span class="keyword"&gt;return&lt;/span&gt; &lt;span class="local-variable"&gt;this&lt;/span&gt;.get(&lt;span class="string"&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;span class="content"&gt;first_name&lt;/span&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;/span&gt;) + &lt;span class="string"&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;span class="content"&gt; &lt;/span&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;/span&gt; + &lt;span class="local-variable"&gt;this&lt;/span&gt;.get(&lt;span class="string"&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;span class="content"&gt;last_name&lt;/span&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;/span&gt;);
  }).property(&lt;span class="string"&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;span class="content"&gt;first_name&lt;/span&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;/span&gt;, &lt;span class="string"&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;span class="content"&gt;last_name&lt;/span&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;/span&gt;)
});
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;This is an extension of &lt;code&gt;Ember.Resource&lt;/code&gt;, which is defined in &lt;code&gt;ember-rest.js&lt;/code&gt; as
an extension of &lt;code&gt;Ember.Object&lt;/code&gt;. The &lt;code&gt;resourceUrl&lt;/code&gt; is the base url of the
resource.&lt;/p&gt;

&lt;p&gt;Also of interest in the model is the computed property &lt;code&gt;fullName&lt;/code&gt;, which returns
a concatenation of &lt;code&gt;first_name&lt;/code&gt; and &lt;code&gt;last_name&lt;/code&gt;. It defines these properties as
dependencies with &lt;code&gt;property(&amp;#39;first_name&amp;#39;, &amp;#39;last_name&amp;#39;)&lt;/code&gt;. If either of those
dependencies is updated, then &lt;code&gt;fullName&lt;/code&gt; will be updated too. Any bindings to
&lt;code&gt;fullName&lt;/code&gt; in views will also be updated.&lt;/p&gt;
&lt;h3&gt;Controller&lt;/h3&gt;
&lt;p&gt;Our Ember-based contacts controller is very simple:&lt;/p&gt;

&lt;div class="code-header"&gt;app/assets/javascripts/app/controllers/contacts.js&lt;/div&gt;
&lt;div class="highlight javascript "&gt;&lt;div class="scroller"&gt;&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td class="line-numbers"&gt;&lt;pre&gt;1
2
3
&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;App.contactsController = Ember.ResourceController.create({
  &lt;span class="key"&gt;resourceType&lt;/span&gt;: App.Contact
});
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Instead of defining a class like &lt;code&gt;App.Contact&lt;/code&gt;, we&amp;#39;re creating
&lt;code&gt;App.contactsController&lt;/code&gt; as an object. It&amp;#39;s an instance of
&lt;code&gt;Ember.ResourceController&lt;/code&gt;, which is defined in &lt;code&gt;ember-rest.js&lt;/code&gt; as a thin
extension to an &lt;code&gt;Ember.ArrayController&lt;/code&gt;. Its only configured property is
&lt;code&gt;resourceType&lt;/code&gt;, which links it to our model. The controller knows enough to use
the &lt;code&gt;resourceUrl&lt;/code&gt; from the model to query resources (although the &lt;code&gt;resourceUrl&lt;/code&gt;
can be overridden at the controller level if needed).&lt;/p&gt;
&lt;h3&gt;Views&lt;/h3&gt;
&lt;p&gt;Let&amp;#39;s now check out our Ember views.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;ListContactsView&lt;/code&gt; renders the listing:&lt;/p&gt;

&lt;div class="code-header"&gt;app/assets/javascripts/app/views/contacts/list.js&lt;/div&gt;
&lt;div class="highlight javascript "&gt;&lt;div class="scroller"&gt;&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td class="line-numbers"&gt;&lt;pre&gt;1
2
3
4
5
6
7
8
&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;App.ListContactsView = Ember.View.extend({
  &lt;span class="key"&gt;templateName&lt;/span&gt;:    &lt;span class="string"&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;span class="content"&gt;app/templates/contacts/list&lt;/span&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;/span&gt;,
  &lt;span class="key"&gt;contactsBinding&lt;/span&gt;: &lt;span class="string"&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;span class="content"&gt;App.contactsController&lt;/span&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;/span&gt;,

  &lt;span class="function"&gt;refreshListing&lt;/span&gt;: &lt;span class="keyword"&gt;function&lt;/span&gt;() {
    App.contactsController.findAll();
  }
});
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;While &lt;code&gt;ShowContactView&lt;/code&gt; renders each row within the listing:&lt;/p&gt;

&lt;div class="code-header"&gt;app/assets/javascripts/app/views/contacts/show.js&lt;/div&gt;
&lt;div class="highlight javascript "&gt;&lt;div class="scroller"&gt;&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td class="line-numbers"&gt;&lt;pre&gt;1
2
3
4
5
&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;App.ShowContactView = Ember.View.extend({
  &lt;span class="key"&gt;templateName&lt;/span&gt;: &lt;span class="string"&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;span class="content"&gt;app/templates/contacts/show&lt;/span&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;/span&gt;,
  &lt;span class="key"&gt;classNames&lt;/span&gt;:   [&lt;span class="string"&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;span class="content"&gt;show-contact&lt;/span&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;/span&gt;],
  &lt;span class="key"&gt;tagName&lt;/span&gt;:      &lt;span class="string"&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;span class="content"&gt;tr&lt;/span&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;/span&gt;
});
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Each view is associated with a template via &lt;code&gt;templateName&lt;/code&gt;. The rendered
template is contained within an html element that is mapped to its corresponding
view. By default this is a &lt;code&gt;div&lt;/code&gt;, although views can override this with the
&lt;code&gt;tagName&lt;/code&gt; property. This element can be customized further with &lt;code&gt;classNames&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Also note the &lt;code&gt;contactsBinding&lt;/code&gt; property on &lt;code&gt;App.ListContactsView&lt;/code&gt;, which binds
the controller&amp;#39;s data to this view as the property &lt;code&gt;contacts&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;Templates&lt;/h3&gt;
&lt;p&gt;Let&amp;#39;s see how each of these views is templated in
&lt;a href="http://handlebarsjs.com"&gt;Handlebars&lt;/a&gt;. First up is our listing:&lt;/p&gt;

&lt;div class="code-header"&gt;app/assets/javascripts/app/templates/contacts/list.handlebars&lt;/div&gt;
&lt;div class="highlight handlebars "&gt;&lt;div class="scroller"&gt;&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td class="line-numbers"&gt;&lt;pre&gt;1
2
3
4
5
6
7
8
9
&lt;strong&gt;10&lt;/strong&gt;
11
12
13
&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="tag"&gt;&amp;lt;table&amp;gt;&lt;/span&gt;
  &lt;span class="tag"&gt;&amp;lt;thead&amp;gt;&lt;/span&gt;
    &lt;span class="tag"&gt;&amp;lt;tr&amp;gt;&lt;/span&gt;
      &lt;span class="tag"&gt;&amp;lt;th&amp;gt;&lt;/span&gt;ID&lt;span class="tag"&gt;&amp;lt;/th&amp;gt;&lt;/span&gt;
      &lt;span class="tag"&gt;&amp;lt;th&amp;gt;&lt;/span&gt;Name&lt;span class="tag"&gt;&amp;lt;/th&amp;gt;&lt;/span&gt;
    &lt;span class="tag"&gt;&amp;lt;/tr&amp;gt;&lt;/span&gt;
  &lt;span class="tag"&gt;&amp;lt;/thead&amp;gt;&lt;/span&gt;
  &lt;span class="tag"&gt;&amp;lt;tbody&amp;gt;&lt;/span&gt;
  &lt;span class="inline"&gt;&lt;span class="inline-delimiter"&gt;{{#&lt;/span&gt;&lt;span class="attribute-name"&gt;each&lt;/span&gt; &lt;span class="attribute-name"&gt;contacts&lt;/span&gt;&lt;span class="inline-delimiter"&gt;}}&lt;/span&gt;&lt;/span&gt;
    &lt;span class="inline"&gt;&lt;span class="inline-delimiter"&gt;{{&lt;/span&gt;&lt;span class="attribute-name"&gt;view&lt;/span&gt; &lt;span class="attribute-name"&gt;App.ShowContactView&lt;/span&gt; &lt;span class="attribute-name"&gt;contactBinding&lt;/span&gt;=&lt;span class="string"&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;span class="content"&gt;this&lt;/span&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span class="inline-delimiter"&gt;}}&lt;/span&gt;&lt;/span&gt;
  &lt;span class="inline"&gt;&lt;span class="inline-delimiter"&gt;{{/&lt;/span&gt;&lt;span class="attribute-name"&gt;each&lt;/span&gt;&lt;span class="inline-delimiter"&gt;}}&lt;/span&gt;&lt;/span&gt;
  &lt;span class="tag"&gt;&amp;lt;/tbody&amp;gt;&lt;/span&gt;
&lt;span class="tag"&gt;&amp;lt;/table&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;This template loops through contacts, which are bound to
&lt;code&gt;App.contactsController&lt;/code&gt;, using the &lt;code&gt;each&lt;/code&gt; helper and renders each one using
&lt;code&gt;ShowContactView&lt;/code&gt;. Because &lt;code&gt;ShowContactView&lt;/code&gt; has a &lt;code&gt;tagName&lt;/code&gt; of &lt;code&gt;tr&lt;/code&gt;, a new row
will be inserted for each record. It will also render the &lt;code&gt;show&lt;/code&gt; template:&lt;/p&gt;

&lt;div class="code-header"&gt;app/assets/javascripts/app/templates/contacts/show.handlebars&lt;/div&gt;
&lt;div class="highlight handlebars "&gt;&lt;div class="scroller"&gt;&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td class="line-numbers"&gt;&lt;pre&gt;1
2
3
4
&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="tag"&gt;&amp;lt;td&amp;gt;&lt;/span&gt;&lt;span class="inline"&gt;&lt;span class="inline-delimiter"&gt;{{&lt;/span&gt;&lt;span class="attribute-name"&gt;contact.id&lt;/span&gt;&lt;span class="inline-delimiter"&gt;}}&lt;/span&gt;&lt;/span&gt;&lt;span class="tag"&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
&lt;span class="tag"&gt;&amp;lt;td&lt;/span&gt; &lt;span class="attribute-name"&gt;class&lt;/span&gt;=&lt;span class="string"&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;span class="content"&gt;data&lt;/span&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span class="tag"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="inline"&gt;&lt;span class="inline-delimiter"&gt;{{&lt;/span&gt;&lt;span class="attribute-name"&gt;contact.fullName&lt;/span&gt;&lt;span class="inline-delimiter"&gt;}}&lt;/span&gt;&lt;/span&gt;
&lt;span class="tag"&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Notice how the &lt;code&gt;contactBinding&lt;/code&gt; in &lt;code&gt;list.handlebars&lt;/code&gt; is passed through to the
&lt;code&gt;show&lt;/code&gt; view, which can reference the object as &lt;code&gt;contact&lt;/code&gt; in its template.&lt;/p&gt;
&lt;h2&gt;All together now&lt;/h2&gt;
&lt;p&gt;Let&amp;#39;s pull this all together in a single server-rendered ERB view:&lt;/p&gt;

&lt;div class="code-header"&gt;app/views/contacts/index.html.erb&lt;/div&gt;
&lt;div class="highlight html "&gt;&lt;div class="scroller"&gt;&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td class="line-numbers"&gt;&lt;pre&gt;1
2
3
4
5
6
7
8
9
&lt;strong&gt;10&lt;/strong&gt;
11
&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="tag"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;Contacts&lt;span class="tag"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;

&lt;span class="tag"&gt;&amp;lt;script&lt;/span&gt; &lt;span class="attribute-name"&gt;type&lt;/span&gt;=&lt;span class="string"&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;span class="content"&gt;text/x-handlebars&lt;/span&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span class="tag"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="inline"&gt;  {{ view App.ListContactsView }}&lt;/span&gt;
&lt;span class="tag"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

&lt;span class="tag"&gt;&amp;lt;script&lt;/span&gt; &lt;span class="attribute-name"&gt;type&lt;/span&gt;=&lt;span class="string"&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;span class="content"&gt;text/javascript&lt;/span&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span class="tag"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="inline"&gt;  &lt;span class="predefined"&gt;$&lt;/span&gt;(&lt;span class="keyword"&gt;function&lt;/span&gt;() {
    App.contactsController.loadAll(&amp;lt;%= &lt;span class="error"&gt;@&lt;/span&gt;contacts.to_json.html_safe %&amp;gt;);
  });&lt;/span&gt;
&lt;span class="tag"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;The first script block is written in Handlebars, as indicated by its &lt;code&gt;type&lt;/code&gt;.
It uses the Ember &lt;code&gt;view&lt;/code&gt; helper to render &lt;code&gt;App.ListContactsView&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The javascript block is a bit of an optimization. It loads contacts, fetched in
our controller&amp;#39;s &lt;code&gt;index&lt;/code&gt; action, into our Ember-based &lt;code&gt;App.contactsController&lt;/code&gt;.
The reason for this is simple: we can improve performance by loading contacts in
the same request as the page. A simpler alternative to calling &lt;code&gt;loadAll()&lt;/code&gt; would
be to find all contacts after jQuery has loaded, like so:&lt;/p&gt;
&lt;div class="highlight handlebars "&gt;&lt;div class="scroller"&gt;&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td class="line-numbers"&gt;&lt;pre&gt;1
2
3
4
5
&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="tag"&gt;&amp;lt;script&lt;/span&gt; &lt;span class="attribute-name"&gt;type&lt;/span&gt;=&lt;span class="string"&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;span class="content"&gt;text/javascript&lt;/span&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span class="tag"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="inline"&gt;  &lt;span class="predefined"&gt;$&lt;/span&gt;(&lt;span class="keyword"&gt;function&lt;/span&gt;() {
    App.contactsController.findAll();
  });&lt;/span&gt;
&lt;span class="tag"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Let&amp;#39;s recap what we&amp;#39;ve done here.&lt;/strong&gt; We first configured a REST interface to
our data in Rails. Next we configured our Ember controller and model to load
data from that interface via &lt;code&gt;ember-rest.js&lt;/code&gt;. Finally, we hooked up our Ember
views and templates to our controller&amp;#39;s data.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Let&amp;#39;s also recap what we &lt;em&gt;haven&amp;#39;t&lt;/em&gt; done here.&lt;/strong&gt; Thanks to &lt;code&gt;ember-rest.js&lt;/code&gt;, we
haven&amp;#39;t needed to write any ajax code to query our REST interface. And thanks to
Ember, we haven&amp;#39;t needed to write code to update our views when contacts are
loaded into the controller&amp;#39;s array.&lt;/p&gt;

&lt;p&gt;Ember will really begin to shine when we see that our views are kept in sync
even as contacts are added, updated, and removed. Speaking of which, my next
post will cover just that...&lt;/p&gt;

&lt;hr&gt;

&lt;p&gt;&lt;em&gt;Please continue on to
&lt;a href="/blog/2012/01/31/beginning-ember-js-on-rails-part-3/"&gt;Beginning Ember.js on Rails: Part 3&lt;/a&gt;,
the final part in this series.&lt;/em&gt;&lt;/p&gt;
</content>
  </entry>
</feed>
