Cells Got content_for Support.

{{{
After decades of struggling with myself, and after a fantastic “RubyConf Australia”:http://www.rubyconf.org.au/ with lots of love I finally managed to give cells users support for a global (brrr) @#content_for@ helper.

h3. Using It.

The new helper is added by including the “cells-capture”:https://github.com/apotonick/cells-capture gem into your @Gemfile@.

gem 'cells-capture'

Cells need to declare explicitly that they want @#content_for@ to access the global buffer by including @Cell::Rails::Capture@. This is meant to remind users that they’re kinda breaking their encapsulation (although it feels handy, I admit).

class BassistCell < Cell::Rails
  include Cell::Rails::Capture

  def show
    render
  end
end

You can now use the helper in your views – it will append passed content to the global buffer.

%div
  - content_for :javascripts
    $('#pick').append("Yo!")

h3. Now What Is Your Problem?

We want cells users to have maximum comfortability, that is why the new helper is here. However, there are two problems with this approach.

* You’re changing state of a global variable from a well-encapsulated cell.
* A cached cell will mess up the global as you expect the cell to append something but it actually doesn’t (remember, there’s a cache hit).

Especially the latter is a problem: Imagine you’re rendering a page with a cached cell: the JavaScript of this component will be lost as the @#content_for@ block is never called! This is a well-known problem in traditional Rails views where people call @#content_for@ in a @#cache@ block.

h3. A Way Out?

A more explicit way of collection JavaScript from view components could help.

render_cell(:bassist, :play) do |cell|
  content_for(:global_js, cell.js)
end

Here, instead of calling @#content_for@ in the cell’s view, you dedicate an additional method to it responsible for rendering the JavaScript (or any other content).

class BassistCell < Cell::Rails
  cache :play

  def play
    render # usually, content_for happens here.
  end

  def js
    render # this could be a JS template
  end
end

The content of the @#js@ view will be added to the @:global_js@ buffer. The cool thing: It will be invoked even when @#play@ is cached!

Anyway, let us know how you use it and enjoy.
}}}

Advertisement

One thought on “Cells Got content_for Support.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s