Basic Rails API Caching

Rails performance out of the box is acceptable for prototypes and small applications with limited traffic. However as your application grows in popularity you will inevitably be faced with the decision to either add more servers, or use your existing servers more efficiently. Complex caching strategies can be incredibly difficult to implement correctly, but simple caching layers can go a long way.

In this post I’ll explain two basic Rails caching mechanisms and explain some of the costs and benefits of each.

HTTP Caching

If your API responses are mostly static content like a list of available products, then HTTP Caching can be a very effective solution. Even something as low as a one minute cache can move the vast majority of your requests to a CDN like CloudFlare or an in-memory store like rack cache.

Specifying the expiration time is simple. In your controller action just call expires_in with the time:

class ProductsController < ApplicationController
  def index
    expires_in 1.minute, public: true
    @products = Product.all
  end
end

This will result in a header being set to Cache-Control: max-age=60, public which any CDN will pick up and serve for you instead of the request hitting your server.

This solution works well when the content is mostly static but it comes with the downside that changes to your content will not be seen for up to one minute (or whichever time you have chosen).

Conditional GET

Another option is using ETags or Last-Modified times to know what version of the resource the client has last seen and returning a HTTP 304 Not Modified response with no content if the resource has not changed.

To set this up in a controller you can either use the fresh_when or stale? methods. Here is an example using the fresh_when method.

class ProductsController < ApplicationController
  def show
    @product = Product.find(params[:id])
    fresh_when(etag: @product, last_modified: @product.created_at, public: true)
  end
end

This method attaches an ETag header and a Last-Modified header to every product response. Now if you make a request for a given product you will see the headers in the response:

curl -i localhost:3000/products/1.json
HTTP/1.1 200 OK
ETag: "91206795ac4c5cd1b02d8fcbc752b97a"
Last-Modified: Mon, 27 May 2014 09:00:00 GMT
...

And if you make the same request but include the ETag in a If-None-Match header, the server can return 304 with empty content and save all the time it would have spent rendering the content.

curl -i localhost:3000/products/1.json \
  --header 'If-None-Match: "91206795ac4c5cd1b02d8fcbc752b97a"'
HTTP/1.1 304 Not Modified
Etag: "91206795ac4c5cd1b02d8fcbc752b97a"
Last-Modified: Mon, 27 May 2014 09:00:00 GMT
...

The other option is to use the If-Modified-Since header in the request, which will have the same result:

curl -i localhost:3000/products/1.json \
  --header 'If-Modified-Since: Mon, 27 May 2014 09:00:00 GMT'
HTTP/1.1 304 Not Modified
Etag: "91206795ac4c5cd1b02d8fcbc752b97a"
Last-Modified: Mon, 27 May 2014 09:00:00 GMT
...

This method still requires a request to be made to the Rails app, and the product still has to be pulled from the database to determine the created_at time. However, rendering the response body can be a substantial portion of each server response so this is a simple way to save a lot of time.

These examples are only the beginning of the caching options Rails offers. As of Rails 4 page caching as well as action caching have been pulled out into their own gems and are worth looking at if you need those options.

Finally if you are ready for something a little more robust you can read about Basecamp’s Russian Doll Caching to see how they solve these problems.

Building A Go Web App with Revel on Heroku

I’ve been interested in Go for a long time now. The language has lots of aspects that make it well suited for building modern web applications including its powerful standard library, concurrency primitives, and impressive performance benchmarks. The community is also gaining a lot of ground in terms of tooling, web frameworks, and other resources for creating sites in Go.

In this post I will show you how to create a basic app in Go and how to host it on Heroku.

If you do not have Go installed on your system, you can do so on a mac with $ brew install go or follow the instructions here. Also if you’re interested in learning the basics of Go, be sure to check out A Tour of Go.

If you get stuck you can find all of the code for this post at github.com/jtescher/example-revel-app.

Creating a Revel App

Revel Logo

Revel is a high-productivity web framework for the Go language. It has an impressive feature set and is much more in line with the rails “convention over configuration” approach than most other Go web frameworks.

To get the project started, first install Revel into your $GOPATH:

$ go get github.com/revel/cmd/revel

Then we can create a new app with the revel new command. Remember you should use your own github username below:

$ revel new github.com/jtescher/blog

And we can start up the app using the revel run command. Again use your github usename, not mine.

$ revel run github.com/jtescher/blog
~
~ revel! http://robfig.github.com/revel
~
INFO  2014/05/11 16:50:10 revel.go:292: Loaded module static
INFO  2014/05/11 16:50:10 revel.go:292: Loaded module testrunner
INFO  2014/05/11 16:50:10 run.go:57: Running blog (github.com/jtescher/blog) in dev mode
INFO  2014/05/11 16:50:10 harness.go:157: Listening on :9000
INFO  2014/05/11 16:50:23 revel.go:292: Loaded module testrunner
INFO  2014/05/11 16:50:23 revel.go:292: Loaded module static
INFO  2014/05/11 16:50:23 main.go:29: Running revel server
Go to /@tests to run the tests.

Now you can go to localhost:9000 and you should see the welcome page.

Revel Welcome Page

Serving Content From Revel

Revel has an easily understood MVC structure and ships with bootstrap by default. You can read more about the flow of control through a Revel app in their excellent core concepts documentation, but for now let’s just render some custom content by adjusting the App/index.html view. Revel uses Go’s built in templating for HTML rendering.

<!-- app/views/App/index.html -->



<div class="container">
  <div class="hero-unit">
    <h1>Hello from Revel!</h1>
    <p>Creating HTML pages is very straightforward.</p>
    <p><a class="btn btn-primary btn-large" role="button">Awesome</a></p>
  </div>

  <div class="row">
    <div class="span6">
      
    </div>
  </div>
</div>


And if you reload the page you should see your changes.

Custom Revel Content

Deploying The App

Deploying a Revel app to Heroku is quite simple. First we create a .godir file at the root of our project with the path to the project in it.

$ echo "github.com/jtescher/blog" > .godir

Then we can create the app on Heroku using a buildpack.

$ heroku create -b https://github.com/robfig/heroku-buildpack-go-revel.git

And finally we can push our app to Heroku.

$ git push heroku
$ heroku open

And that’s it! Your Revel app should now be live.

Creating A Metrics Dashboard With Ember.js, Bootstrap, and Rails - Part 3

This is part three of a series on building a metrics dashboard with Ember, Bootstrap, and Rails. Over the next few weeks I will be building out more functionality and writing posts to cover that. If you haven’t read part one and part two then that’s a good place to start.

In part two we ended up with an Ember app that rendered dynamic tables. If you followed along, your page should now look like this:

Part Two Final

Today we’re going to add some graphs and see how Ember components work.

Remember, if you get stuck you can find all of the code for this post at github.com/jtescher/example-ember-rails-dashboard.

Choosing The Right Library

Highcharts Demo

There are many good options when it comes to JavaScript graphing, charting, and visualizations. I find highcharts to be a good place to get started and it is free for non-commercial uses! If you find yourself needing more control or having a very specific requirement you can always look at projects like d3.js.

Adding Highcharts

Let’s download the latest version of highcharts to our vendor/assets/javascripts directory.

$ curl http://code.highcharts.com/4.0.1/highcharts.js \
    -o vendor/assets/javascripts/highcharts-4.0.1.js

And then require the file in app/assets/javascripts/application.js

...
//= require jquery
//= require accounting-0.3.2
//= require highcharts-4.0.1
//= require_tree .

Creating The Ember Component

Ember makes adding reusable components quite simple. We can add a component that represents a specific chart we want to show on the screen and have ember re-render the chart whenever the data changes. You can read more about how the Ember components work here.

As an example we can add a highcharts column chart to show revenue by product. First let’s add the component in our app/assets/javascripts/templates/orders.hbs file:

<h1>Orders</h1>



<table class='table table-striped'>
...

Then we can add the template for the component in app/assets/javascripts/templates/components/column-chart.hbs:

<div  style='width: 100%;'></div>

And finally we can define the component in app/assets/javascripts/components/column-chart.js.coffee:

Dashboard.ColumnChartComponent = Ember.Component.extend
  tagName: 'div'
  classNames: ['highcharts']

  contentChanged: (->
    @rerender()
  ).observes('series')

  didInsertElement: ->
    $("##{@chartId}").highcharts({
      chart: { type: 'column' },
      title: { text: 'Revenue by Product' },
      legend: { enabled: false },
      xAxis: {
        title: {
          text: 'Product Number'
        }
      },
      series: [{
        name: 'Quantity',
        data: [4, 4]
      }, {
        name: 'Revenue',
        data: [10.0, 10.0]
      }]
    })

  willDestroyElement: ->
    $("##{@chartId}").highcharts().destroy()

Then when you reload the page it should look like this:

Orders Static Column Chart

Binding Data To The Ember Component

The chart we have is currently always showing the same series because we hard coded it in the component. Let’s now make this dynamic by adding the data in the route and using data bindings.

First let’s update the data in our orders route to include a product id.

# app/assets/javascripts/routes/orders_route.js.coffee
Dashboard.OrdersRoute = Ember.Route.extend({
  model: ->
    [
      {
        id: 1,
        firstName: 'James',
        lastName: 'Deen',
        quantity: 1,
        revenue: '10.00',
        productId: 0,
      },
      {
        id: 2,
        firstName: 'Alex',
        lastName: 'Baldwin',
        quantity: 2,
        revenue: '20.00',
        productId: 1,
      }
    ]
})

And then we can build our chart series in the orders controller (this is a very simplistic example):

Dashboard.OrdersController = Ember.ArrayController.extend({

  ...

  chartSeries: (->
    revenues = @map((order)->
      parseFloat(order.revenue)
    )
    quantities = @mapBy('quantity')

    [
      {
        name: 'Quantity',
        data: quantities
      },
      {
        name: 'Revenue',
        data: revenues
      }
    ]
  ).property('@each')

})


We can then bind chartSeries in orders.hbs:

<h1>Orders</h1>



<table class='table table-striped'>

And finally use series in our chart component:

# app/assets/javascripts/components/column-chart.js.coffee
...
didInsertElement: ->
  $("##{@chartId}").highcharts({
    chart: { type: 'column' },
    title: { text: 'Revenue by Product' },
    legend: { enabled: false },
    xAxis: {
      title: {
        text: 'Product Number'
      }
    },
    series: @series
  })
...

We then end up with our final dynamic chart rendered by Ember: Orders Static Column Chart

Creating A Metrics Dashboard With Ember.js, Bootstrap, and Rails - Part 2

This is part two of a series on building a metrics dashboard with Ember, Bootstrap, and Rails. Over the next few weeks I will be building out more functionality and writing posts to cover that. If you haven’t read part one then that’s a good place to start. You can find part three here when you are finished.

In part one we ended up with a Rails app that generated the Ember app that rendered our metrics page. If you followed along your page should now look like this:

Part One Final

Today we’re going to add some tables and see how data flows through an Ember app. If you are not familiar with Ember’s conventions and idioms you should first read their excellent documentation and guides before continuing here.

Remember, if you get stuck you can find all of the code for this post at github.com/jtescher/example-ember-rails-dashboard.

Preparing the application

Before we add any more content let’s update our Ember application template and add a basic structure with some navigation in app/assets/javascripts/templates/application.hbs.

<div class='container'>

  <header class='masthead'>
    <nav class='navbar navbar-default' role='navigation'>
      <div class='container-fluid'>
        <div class='navbar-header'>
          <button type='button' class='navbar-toggle'
              data-toggle='collapse' data-target='#main-nav-collapse'>
            <span class='sr-only'>Toggle navigation</span>
            <span class='icon-bar'></span>
            <span class='icon-bar'></span>
            <span class='icon-bar'></span>
          </button>
          Dashboard
        </div>

        <div class='collapse navbar-collapse' id='main-nav-collapse'>
          <ul class='nav navbar-nav'>
            
              Home
            
          </ul>
        </div>
      </div>
    </nav>
  </header>

  <section class='main-content'>
    
  </section>

</div>

And let’s add an index template so we know when we’re on the home page in app/assets/javascripts/templates/index.hbs.

<div class='jumbotron'>
  <h1>Hello from Ember.js!</h1>
  <p>Let's see some metrics.</p>
</div>

If you reload the page you should now see this:

Ember application template

Creating Tables with Ember and Handlebars

Often the simplest way to display metrics data is to just put it all in a table. I find that it is often helpful when creating HTML with JavaScript to first start out with the final result and slowly add dynamic content in pieces. Let’s create an example of this to display some financial data about our sales process.

Step one is to create the Ember route to get to this URL. Let’s edit app/assets/javascripts/router.js.coffee and add it:

# app/assets/javascripts/router.js.coffee
Dashboard.Router.map ()->
  @resource('orders')

And we can then create an idea of what we want the page to look like by mocking up some static HTML in app/assets/javascripts/templates/orders.hbs

<h1>Orders</h1>
<table class='table table-striped'>
  <tr>
    <th>#</th>
    <th>First Name</th>
    <th>Last Name</th>
    <th>Quantity</th>
    <th>Revenue</th>
  </tr>
  <tr>
    <td>1</td>
    <td>James</td>
    <td>Deen</td>
    <td>1</td>
    <td>$10.00</td>
  </tr>
  <tr>
    <td>2</td>
    <td>Alex</td>
    <td>Baldwin</td>
    <td>2</td>
    <td>$20.00</td>
  </tr>
</table>

<p>Total Quantity: <b>3</b></p>
<p>Total Revenue: <b>$30</b></p>

Then we can add a link to this page in our application.hbs file (the double link-to is an annoying hack but explained here):

...
<div class='collapse navbar-collapse' id='main-nav-collapse'>
  <ul class='nav navbar-nav'>
    
      Home
    
    
      Orders
    
  </ul>
</div>
...

Then if you reload and follow the orders nav link you should see this:

Static Orders

Creating Dynamic Tables

In Ember, a template typically retrieves information to display from a controller, and the controller is set up by its route. Let’s make this table dynamic by assigning the data required to build it in the OrdersRoute.

# app/assets/javascripts/routes/orders_route.js.coffee
Dashboard.OrdersRoute = Ember.Route.extend({
  model: ->
    [
      {
        id: 1,
        firstName: 'James',
        lastName: 'Deen',
        quantity: 1,
        revenue: '10.00',
      },
      {
        id: 2,
        firstName: 'Alex',
        lastName: 'Baldwin',
        quantity: 2,
        revenue: '20.00',
      }
    ]
})

And then we set up the controller to process the totals in the OrdersController.

# app/assets/javascripts/controllers/orders_controller.js.coffee
Dashboard.OrdersController = Ember.ArrayController.extend({

  totalQuantity: (->
    @reduce(((previousValue, order) ->
      previousValue + order.quantity
    ), 0)
  ).property('@each')

  totalRevenue: (->
    @reduce(((previousValue, order) ->
      previousValue + parseFloat(order.revenue)
    ), 0)
  ).property('@each')

})

And this lets us use the data provided by the controller in the template:

<h1>Orders</h1>
<table class='table table-striped'>
  <tr>
    <th>#</th>
    <th>First Name</th>
    <th>Last Name</th>
    <th>Quantity</th>
    <th>Revenue</th>
  </tr>
  
  <tr>
    <td></td>
    <td></td>
    <td></td>
    <td></td>
    <td></td>
  </tr>
  
</table>

<p>Total Quantity: <b></b></p>
<p>Total Revenue: <b></b></p>

If you reload the page it should now look like this:

Dynamic Orders

Formatting Values With Helpers

The image above looks pretty good but we seem to have lost our currency formatting. There are a few good libraries for formatting currencies in JavaScript, and Ember makes it simple to access these libraries in your handlebars templates. Let’s add the accounting.js library to format our revenue numbers.

First install the library to vendor/assets/javascripts:

$ curl https://raw.github.com/josscrowcroft/accounting.js/master/accounting.js -o vendor/assets/javascripts/accounting-0.3.2.js

Then include it in your application.js file:

//= require jquery
//= require accounting-0.3.2
//= require_tree .

Then create a currency_helpers.js.coffee file to wrap the library.

# app/assets/javascripts/helpers/currency_helpers.js.coffee
Ember.Handlebars.registerBoundHelper('numberToCurrency', (number) ->
  accounting.formatMoney(number)
)

And finally we can use this helper in our orders.hbs view:

...

  <tr>
    <td></td>
    <td></td>
    <td></td>
    <td></td>
    <td></td>
  </tr>
  
</table>

<p>Total Quantity: <b></b></p>
<p>Total Revenue: <b></b></p>

Now that our numbers are formatted properly you can reload the page and see our final result for part 2:

Currency Helpers

You can now go on to part three and start adding some charts!

Creating A Metrics Dashboard With Ember.js, Bootstrap, and Rails - Part 1

This is part one of a series on building a metrics dashboard with Ember, Bootstrap, and Rails. Over the next few weeks I will be building out more functionality and writing posts to cover that. You can find part two here.

There are some services that will provide dashboards and visualizations for you like Geckoboard, but once you need to provide custom analytics and graphs to clients or co-workers you will need something a little more flexible.

Today we’re going to assemble the first pieces of this app by creating a Rails server, an Ember.js App and some basic Bootstrap styling.

You can find all of the code for this post at github.com/jtescher/example-ember-rails-dashboard.

The Rails Server

We want to be able to expose all of our stats from various internal and third party services with a consistent API so this server will primarily handle authentication and data transformation. This server could just as easily be written in Node.js or any language/framework, but for now we’ll stick with Rails.

Create the server (skipping ActiveRecord and TestUnit because we don’t need a database for this app and we will be testing with Rspec):

$ rails new dashboard --skip-test-unit --skip-active-record

Then we want to add the route that will render our dashboard. We will use the home controller and the index action:

$ rails generate controller Home index --no-helper --no-assets

We wil route everything to Ember, so replace your config/routes.rb file with the following:

# config/routes.rb
Rails.application.routes.draw do
  root 'home#index'
end

If you start your server now with $ rails server and open up localhost:3000 you should see the following:

Home screen

The Theme

We will be using stock Twitter Bootstrap for this project so let’s add the bootstrap-sass gem to our Gemfile.

...
# Front-end framework for developing responsive, mobile first projects on the web.
gem 'bootstrap-sass', '~> 3.1.1'

And configure it by creating a bootstrap_config.css.scss file.

// app/assets/stylesheets/bootstrap_config.css.scss
@import "bootstrap";

Then we can change the home/index.html.erb view to the following:

<div class='container'>
  <div class='jumbotron'>
    <h1>Hello from Twitter Bootstrap!</h1>
    <p>Lots of predefined style that makes things easy to prototype!</p>
  </div>
</div>

And when you restart the server you should see:

Bootstrap Defaults

The Ember.js App

We can now add the ember-rails and ember-source gems for Ember assets and scaffolding to our Gemfile.

...
# JS framework for creating ambitious web applications.
gem 'ember-rails',  '~> 0.14.1'
gem 'ember-source', '~> 1.5.0'

And install the Ember assets with:

$ rails generate ember:bootstrap

We can also remove turbolinks as ember will handle all the routing after the first page load. Your application.js file should look like this:

//= require jquery
//= require_tree .

I also renamed the generated app/assets/javascripts/application.js.coffee file to be app/assets/javascripts/app.js.coffee to not conflict with the first application.js file.

Next move the html from home/index.html.erb and replace it with the following:

<% # Rendered Entirely in EmberJS. See app/assets/javascripts %>

Then we can move the html generation to ember by placing it in the top level application.hbs handlebars file.

<!-- app/assets/javascripts/templates/application.hbs -->
<div class='container'>
  <div class='jumbotron'>
    <h1>Hello from Ember.js!</h1>
    <p>The link to the home page is here</p>
  </div>
</div>

And the end of part one should be rendered by Ember looking like this:

Final

You can now go on to part two and start building dynamic tables!