Read my latest article: 8 things I look for in a Ruby on Rails app (posted Thu, 06 Jul 2017 16:59:00 GMT)

Setting Akamai Edge-Control headers with Ruby on Rails

Posted by Tue, 19 Jun 2012 04:54:00 GMT

Just a short and sweet little tip.

Several months ago we moved one of our clients over to Akamai’s Content Delivery Network (CDN). Ww were previously using a combination of Amazon S3 and CloudFront with some benefits, but we were finding several key areas of the world were not s covered by Amazon (yet) for asset delivery. Along with that, we really wanted to take advantage of the CDN for more of our HTML content with a lot of complex rules that related to geo-targeting and regionalization of content.

I’ll try to cover those topics in another post, but wanted to share a few tidbits of code that we are using to manage Akamai’s Edge-control caches from within our Rails application.

With Akamai, we’re able to tell their Edge servers whether it should hold on to the response so it can try to avoid an extra request to the origin (aka our Rails application). From Rails, we just added a few helper methods to our controllers so that we can litter our application with various expiration times.

  # Sets the headers for Akamai
  # acceptable formats include:
  #   1m, 10m, 90m, 2h, 5d
  def set_cache_control_for(maxage="20m")
    headers['Edge-control'] = "!no-store, max-age=#{maxage}"
  end

This allows us to do things like:

  class ProductsController < ApplicationController
    def show
      set_cache_control_for('4h')
      @product = Product.find(params[:id])
    end
  end

Then when Akamai gets a request for http://domain.com/products/20-foo-bar, it’ll try to keep a cached copy around for four hours before it hits our server again.

Managing SEO-friendly HTML Titles with Rails

Posted by Wed, 26 Mar 2008 20:41:00 GMT

I’ve seen this come up a few times in the #rubyonrails IRC channel and figured that I’d post a quick entry for future reference.

Problem: HTML titles

You want to have a clean way to manage the titles on your HTML pages.


  <html>
    <head>
      <title>Robby on Rails &mdash; Article Title Goes Here</title>
    </head>
    <body>
      ...

Possible Solution(s):

Since the <title> tag is usually declared in your layout, you need to be able to dynamically update this information from almost every action in your application.

Here are a few ways that I’ve seen this handled.

  1. Use a instance variable, which would have a default value and you could override it in any controller action
  2. Use the content_for method to manage it.

Let’s take a few minutes to look at these two approaches.

Instance Variable

With the instance variable, you might end up with something like:


  # app/views/layouts/application.html.erb
  <title>Robby on Rails &mdash; <%= @html_title || 'Default text here...' -%></title>

Then in a controller action…


  # app/controllers/articles_controller.rb
  def show
    # ...
    @html_title = @article.title
  end

So, that’s one way to handle it and is probably a more common way.

The content_for helper method approach

This solution is very similar (and underneath uses an instance variable).

We’ll use the content_for and a little yield action.


  # app/views/layouts/application.html.erb
  <title>Robby on Rails <%= (html_title = yield :html_title) ? html_title : '&mdash; Default text here...' %></title>

Then we’ll create a helper method.


  # app/helpers/application_helper.rb
  def set_html_title(str="")
    unless str.blank?
      content_for :html_title do
       "&mdash; #{str} " 
      end
    end
  end  

Now, instead of defining the HTML <title> value in the controllers, we’ll just toss this into our html.erb files as necessary.


  <% set_html_title(@article.name) -%>
  ... rest of view

..and that’s pretty much it.

Which is the better solution?

This is where we’ll not find a lot of consensus amongst people. I’m a fan of the content_for-based approach and defining the title in views rather than in controller actions. I’m an advocate of skinny controllers and while I’m not a big fan of messy views, I believe that there is less overhead in managing this within the View-world.

I’d love to hear your thoughts on this. Perhaps you have a more eloquent for managing things like this? Do share. :-)