sd edited this page Sep 12, 2010 · 6 revisions
Clone this wiki locally

Embedded Actions is an extraction of some neat tricks we’ve been using at StreetEasy for the last couple of years.

It provides a simple way to encapsulate both logic and presentation to be reused inside your Rails views. In other words, it lets you include the results of a controller action inside a view.

Lets say your blog app has a home page, and you want to include a little box on the right with the top 10 most visited entries. Your “BlogController” has an “index” action and an “index.rhtml” view. That view contains, among other things, something like:

<div class='sidebar'><%= embed_action :controller => "blog", :action => "top10" %></div>

Now you can implement a “top10” action that looks for the most visited entries, and renders a simplified view that will be included in the initial “index.rhtml” view as part of the response.

But that’s not all. Your “top10” action can use Rails’ responds_to mechanism to provide different views depending on whether the request is for an embedded version or a full page.

def top10
  @entries = Entries.find_top(10)
  respond_to do |format|
    format.embedded { render :template => "top10_embedded", :layout => false }
    format.all      { render :template => "top10" }

And of course, your embedded actions can take parameters, which will be sent to the action just like a regular request’s params hash:

<%= embed_action :action => "top10", :tags => "music" %>

And to put some icing on the top, you can cache your embedded actions using Rails’ fragment caching facilities. In your controller (usually just before you define the action) you declare something along the lines of:

caches_embedded :top_10, :ttl => 60.minutes

And your call to embed_action will use the cached version instead, providing significant performance improvements without increasing the complexity of your application. Cached actions can be cleared using expire_embedded, or using the underlying fragment caching provider options, like :ttl.

In fact, caching might be the most compelling reason to use embedded actions. You can have very simple actions for your “container page” that have some minimal logic (i.e. user is logged in or not) and then delegate individual content blocks to different embedded actions, each one cached with it’s own expiration mechanisms.