Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Ember.js ♥ Rails

Ember.js ♥ Rails

Client and server frameworks that were made for each other.

Given at the Atlanta Ruby User Group on 5/8/13.

Cee3a9b82b1f1738107efaf94423c9bc?s=128

Jason Ardell

May 08, 2013
Tweet

More Decks by Jason Ardell

Other Decks in Programming

Transcript

  1. Ember.js — Rails client and server frameworks that were made

    for each other Atlanta Ruby User Group May 8th, 2013
  2. Jason Ardell Agile Engineering https://github.com/ardell Introductions

  3. Backbone.js AngularJS Ember.js and many more... Javascript MV* Frameworks We’re

    going to be talking a lot about Javascript MV* or MVC frameworks. I’ll use the terms interchangeably. Poll: how many have used a JS MV* Framework including Backbone, Angular, Ember, Knockout, or something else? Backbone? Angular? Ember?
  4. • Recognizable/intuitive project structure • 2-way data binding • Routing

    • Templating (Handlebars, Mustache, jQuery Templates, etc) Javascript MV* Frameworks We need some structure around our javascript applications, otherwise they get nuts. Javascript frameworks help other developers (and future-you) to recognize and maintain the application.
  5. Libraries Frameworks

  6. http://todomvc.com One great way to compare the many javascript frameworks

    that are out there is TodoMVC. It’s the result of a collaboration of lots of different developers who have all built an implementation of a simple TODOs app in around 20 different frameworks.
  7. • Instructional & portable • Only views & controllers •

    Data store is local, non-flaky, & dumb (i.e. unrealistic) In order to illustrate how frameworks differ from libraries, let's look at TodoMVC... What is it? - The same app (todos) built in ~20 different js frameworks (Backbone, Angular, Ember, Knockout, etc) - Intended to be instructional & portable - TodoMVC is good, but it's not the whole picture - only deals with views & controllers - data store is local, non-flaky, & dumb (not very realistic) [as opposed to REST: validations, relations, collaboration] This focus on views & controllers (and it leaves out the back-end) is consistent with most of the javascript frameworks out there: most focus on data-binding and routing, punt on persistence.
  8. Application Architecture db model controller view I’m sure most of

    you are familiar with this traditional application architecture from Rails. We have views that display the user interface, controllers that respond to user actions, models that provide an object-oriented abstraction for our data store, most likely a database.
  9. Application Architecture db model controller view model controller view Client

    Server Javascript MVC applications follow a very similar paradigm, with views, controllers, models, and a data store, with one key difference--the data store is typically a set of web services, which can be implemented in Rails. So you end up with an app-within-an-app.
  10. Views Controllers ORM Data Store ERB HAML Slim ActionController ActiveRecord

    Postgres MongoDB Rails Application Architecture
  11. Views Controllers ORM Data Store ERB HAML Slim ActionController ActiveRecord

    Postgres MongoDB Rails JS Application Architecture On the client side we need to do all the same things we do on the server side, whether we realize it or not. The first way you can do this is the way we were all doing this 5 years ago. It used to be the only way to do it.
  12. Views Controllers ORM Data Store ERB HAML Slim ActionController ActiveRecord

    Postgres MongoDB $.live Application Architecture Rails JS I listen for click events, using jQuery’s live or bind...
  13. Views Controllers ORM Data Store ERB HAML Slim ActionController ActiveRecord

    Postgres MongoDB $.live $.ajax Application Architecture Rails JS use $.ajax
  14. Views Controllers ORM Data Store ERB HAML Slim ActionController ActiveRecord

    Postgres MongoDB $.live $.ajax Restful API Application Architecture Rails JS to hit a restful API
  15. Views Controllers ORM Data Store ERB HAML Slim ActionController ActiveRecord

    Postgres MongoDB $.html $.live $.ajax Restful API Application Architecture Rails JS then update the correct element using $.html This works, but it’s a mess, for several reasons...
  16. Views Controllers ORM Data Store ERB HAML Slim ActionController ActiveRecord

    Postgres MongoDB $.html $.live $.ajax Restful API Not testable Application Architecture Rails JS It's not testable,
  17. Views Controllers ORM Data Store ERB HAML Slim ActionController ActiveRecord

    Postgres MongoDB $.html $.live $.ajax Restful API Not testable Spaghetti Code Application Architecture Rails JS creates spaghetti code,
  18. Views Controllers ORM Data Store ERB HAML Slim ActionController ActiveRecord

    Postgres MongoDB $.html $.live $.ajax Restful API Not testable Spaghetti Code Callback Hell Application Architecture Rails JS leads to callback hell,
  19. Views Controllers ORM Data Store ERB HAML Slim ActionController ActiveRecord

    Postgres MongoDB $.html $.live $.ajax Restful API Not testable Spaghetti Code Callback Hell Non-DRY Application Architecture Rails JS not DRY, so you can’t re-use components...
  20. Views Controllers ORM Data Store ERB HAML Slim ActionController ActiveRecord

    Postgres MongoDB $.html $.live $.ajax Restful API Not testable Spaghetti Code Callback Hell Non-DRY Code Smells Application Architecture Rails JS ... and there are code smells all over the place. If you have an ounce of software craftsmanship in you, this should make you cringe.
  21. Views Controllers ORM Data Store ERB HAML Slim ActionController ActiveRecord

    Postgres MongoDB Rails JS MV* Application Architecture We’re in need of a new approach... Let's try a javascript MVC framework and see how it cleans things up.
  22. Views Controllers ORM Data Store ERB HAML Slim ActionController ActiveRecord

    Postgres MongoDB Backbone.js AngularJS Application Architecture Rails JS MV* Instead of binding events directly to the DOM, I bind to actions using Backbone/Angular,
  23. Views Controllers ORM Data Store ERB HAML Slim ActionController ActiveRecord

    Postgres MongoDB Backbone.js AngularJS Backbone.Sync Angular.HTTP Angular.Resource Application Architecture Rails JS MV* Use Backbone.Sync or Angular.HTTP/Resource
  24. Views Controllers ORM Data Store ERB HAML Slim ActionController ActiveRecord

    Postgres MongoDB Backbone.js AngularJS Backbone.Sync Angular.HTTP Angular.Resource Restful API Application Architecture Rails JS MV* To hit the same restful API,
  25. Views Controllers ORM Data Store ERB HAML Slim ActionController ActiveRecord

    Postgres MongoDB Handlebars Backbone.js AngularJS Backbone.Sync Angular.HTTP Angular.Resource Restful API Application Architecture Rails JS MV* And allow the framework to update my handlebars templates automatically using bindings. This is very cool! Instead of constantly worrying about whether we need to update the view, we write declarative templates so that no matter what state we're in, the template can handle it.
  26. <ul> {{#each books}} <li>{{title}}</li> {{else}} <li class="empty">No results.</li> {{/each}} </ul>

    This is a handlebars template that displays a list of books. Let’s say we start out without any books--it’ll show “No results.” When I add a book, it automatically removes “No results.” and adds the book’s title to the list.
  27. Views Controllers ORM Data Store ERB HAML Slim ActionController ActiveRecord

    Postgres MongoDB Handlebars Backbone.js AngularJS Backbone.Sync Angular.HTTP Angular.Resource Restful API Application Architecture Rails JS MV* So having declarative templates with data binding is a game-changer.
  28. Views Controllers ORM Data Store ERB HAML Slim ActionController ActiveRecord

    Postgres MongoDB Handlebars Backbone.js AngularJS Backbone.Sync Angular.HTTP Angular.Resource Restful API Application Architecture Rails JS MV* But there’s one thing that can still require a lot of customization--the Model layer. Backbone.Sync and Angular HTTP & Resource are great, but they’re minimalistic, for example Backbone.Sync is only 50 lines of code. The reason they’re minimalistic is out of necessity-- JSON APIs aren’t standardized, so they have to handle everything, which means they require a lot of configuration to handle most use cases. And that violates one of the core principles of Rails--convention over configuration.
  29. Views Controllers ORM Data Store ERB HAML Slim ActionController ActiveRecord

    Postgres MongoDB Handlebars Ember.js Ember Data Restful API Rails Ember Application Architecture I’ve found that this combination suits me extremely well. It allows me to write the bare minimum of glue code so that I can quickly start building my application. Here are some areas where Ember really shines...
  30. class Post < ActiveRecord::Base belongs_to :author has_many :comments has_many :tags

    attr_accessible :title, :body end Declare your models similarly to ActiveRecord post.rb @App.Post = DS.Model.extend author: DS.belongsTo('App.Author') comments: DS.hasMany('App.Comment') tags: DS.hasMany('App.Tag') title: DS.attr('string') body: DS.attr('string') post.coffee Ember Awesomeness On the left we have an ActiveRecord model, on the right an Ember Data model (in coffeescript). DS is Ember Data’s namespace. It’s easy to define associations and get cascading saves for free.
  31. Embedded records save HTTP requests (great for mobile btw!) @App.Post

    = DS.Model.extend author: DS.belongsTo('App.Author') comments: DS.hasMany('App.Comment') tags: DS.hasMany('App.Tag') title: DS.attr('string') body: DS.attr('string') post.coffee Ember Awesomeness Another easy win is the ability to sideload related records to reduce the number of HTTP requests that your application makes. This is especially great for mobile since latency over 3g is so high. On a recent project we wanted the user experience to be really snappy after the first load, so we basically sideloaded the user’s entire tree of data into a single request. Once the initial HTTP request finished we never had to hit the server again for read operations.
  32. Embedded records save HTTP requests (great for mobile btw!) @App.Post

    = DS.Model.extend author: DS.belongsTo('App.Author') comments: DS.hasMany('App.Comment', { embedded: true }) tags: DS.hasMany('App.Tag', { embedded: true }) title: DS.attr('string') body: DS.attr('string') post.coffee Ember Awesomeness Another easy win is the ability to sideload related records to reduce the number of HTTP requests that your application makes. This is especially great for mobile since latency over 3g is so high. On a recent project we wanted the user experience to be really snappy after the first load, so we basically sideloaded the user’s entire tree of data into a single request. Once the initial HTTP request finished we never had to hit the server again for read operations.
  33. • Convention over configuration • Yehuda and team (Rails &

    jQuery) • No need to learn a new mental model • Unified stack • Designed to work out-of-the-box with ActiveModel::Serializers Ember Awesomeness Ember shares Rails’ core philosophy of convention over configuration. It can sometimes be magic-y, for instance if a particular controller doesn’t exist, Ember will create an empty one for you! This is why naming conventions are very important (as in Rails). The heavy reliance on convention is due to the fact that the core team is lead by Yehuda Katz, who was a core maintainer on both Rails and jQuery. I like knowing that the team writing my framework understand my server-side framework extremely well, and were part of building the most popular javascript library out there. Since there’s a shared ecosystem there I feel like I didn’t have to learn a new mental model, and I feel like my stack is well-unified. But one of the greatest things about Ember/Ember Data is that it was designed to work out- of-the-box with ActiveModel::Serializers...
  34. Makes your API consistent & intuitive ActiveModel::Serializers ActiveModel::Serializers https://github.com/rails-api/active_model_serializers ActiveModel::Serializers

    is an outstanding gem that helps you build consistent APIs in Rails. The idea is that the serialization structure should be declarative and independent of the serialized format. A serializer can be used to produce equivalent JSON and XML representations of a given model. Here’s how it works...
  35. ActiveModel::Serializers def show @post = Post.find(params[:id]) respond_to do |format| format.html

    format.json { render json: @post } end end posts_controller.rb class PostSerializer < ActiveModel::Serializer attributes :id, :title, :body has_many :comments, :embed => :ids, :include => true has_many :tags, :embed => :ids, :include => true end post_serializer.rb ActiveModel::Serializers You’re probably familiar with the top snippet, it’s from a controller serving up a “show” action for blog posts. Below, we tell ActiveModel::Serializers that we want the serialization of a Post to include id, title, and body attributes, plus embedded comments and tags. Notice I left out created_at and updated_at--this causes those attributes to be left out of the serialization. By the way, you can also add calculated attributes that exist only in the serializer--they help you clean up your API to make it extremely developer-friendly. [pause] Here’s the resulting JSON...
  36. { posts: [{ id: 1, title: "Sample Blog Post", body:

    "Hello world!", comment_ids: [ 1 ], tag_ids: [ 1, 2 ] }], comments: [ { id: 1, body: "Test comment" } ], tags: [ { id: 1, name: 'Ponies' }, { id: 2, name: 'Unicorns' } ] } GET /posts/1.json ActiveModel::Serializers ActiveModel::Serializers The great thing about ActiveModel::Serializers is they’re totally nest-able. If I wanted to change the attributes I include for comments, I just make my changes to the CommentSerializer and it will be automatically updated anywhere where a comment is nested. That’s where the power of ActiveModel::Serializers lies in creating a consistent API.
  37. • Adds Ember generators • Allows you to separate out

    handlebars templates https://github.com/emberjs/ember-rails ActiveModel::Serializers Ember-Rails Gem One other nicety that you’ll want when building Ember apps with Rails is the ember-rails gem. It adds rails generators for installing ember and creating templates and such. And it allows you to separate your handlebars templates into individual files, e.g. posts/ show.handlebars. Then the handlebars templates get compiled down to javascript using the Rails Asset Pipeline as usual.
  38. 1. Peepcode Screencast “Fire up Ember” ($12) https://peepcode.com/products/emberjs ActiveModel::Serializers How

    to learn Ember.js Javascript frameworks can be tough to pick up at first--the stateful MVC model in particular can be challenging to web developers who have only built stateless apps before. Ember has gotten its share of flack for being slow to build great getting-started resources. There are a couple great resources that are relatively new that I’d point you to if you’re interested in learning more about Ember: First, there’s a great screencast from Peepcode that walks you through building a Restaurant Menu app. It was written side-by-side with Yehuda and Tom Dale (Ember’s other main maintainer), so it’s got a lot of practical advice about the _best_ way to use Ember.
  39. 1. Peepcode Screencast “Fire up Ember” ($12) https://peepcode.com/products/emberjs 2. Railscasts

    (parts 1 & 2, $9/mo) http://railscasts.com/episodes/408-ember-part-1 http://railscasts.com/episodes/410-ember-part-2 How to learn Ember.js Also Ryan Bates has created a 2-part series of Railscasts about Ember that you should check out. The most important thing about learning Ember is...
  40. 1. Peepcode Screencast “Fire up Ember” ($12) https://peepcode.com/products/emberjs 2. Railscasts

    (parts 1 & 2, $9/mo) http://railscasts.com/episodes/408-ember-part-1 http://railscasts.com/episodes/410-ember-part-2 ActiveModel::Serializers How to learn Ember.js Pay to learn unless your time is worthless! That you should pay for these resources unless your time is worthless. I’d bet that’s not the case for anybody in this room, so it’s worth $12 not to bang your head against a wall.
  41. 1. Peepcode Screencast “Fire up Ember” ($12) https://peepcode.com/products/emberjs 2. Railscasts

    (parts 1 & 2, $9/mo) http://railscasts.com/episodes/408-ember-part-1 http://railscasts.com/episodes/410-ember-part-2 3. Ember guides, api docs, stack overflow Pay to learn unless your time is worthless! ActiveModel::Serializers How to learn Ember.js Once you’ve been through these resources, feel free to dig into the API and Ember’s guides, and as always, StackOverflow is your friend.s
  42. • Want to work with Ember? full-timers & freelancers needed

    • Need help on a project? we build web apps using Rails and JS MV* frameworks ActiveModel::Serializers Shout-outs A couple shout-outs... If you’re interested in working with Ember, I know of a couple companies in town who are hiring full-time specifically for Ember. And if you’re a freelancer, we’re always looking for great folks to join us for a project. Additionally, if you’re looking to build out an app in Rails and/or a javascript framework, we’d love to talk to you about how we can help make that happen.
  43. Jason Ardell https://github.com/ardell ardell@gmail.com ActiveModel::Serializers Questions? Any questions?

  44. • EmberJS.com, esp: http://emberjs.com/guides/ http://emberjs.com/api/ • StackOverflow: http://stackoverflow.com/questions/tagged/ember.js http://stackoverflow.com/questions/tagged/ember-data •

    Videos from Ember Camp 2013 http://lanyrd.com/2013/ember-camp/ • Ember.js Google Chrome Extension https://github.com/rapheld/ember_inspector ActiveModel::Serializers Additional Resources
  45. • Compiles coffeescript & handlebars • Combines/minifies javascript ActiveModel::Serializers Rails

    Asset Pipeline
  46. • Konacha / Mocha / Chai uses Rails Asset Pipeline

    (nice if you’re writing Coffeescript) • Karma (Testacular) uses conf to load dependencies, multi-browser! • Both can be run via CLI (including continuous integration) ActiveModel::Serializers Testing