{{{
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.
}}}
Nick, thanks for following up on this issue, didn’t even think about calling content_for in the cell block.
LikeLike