Archive for the ‘Cells’ Category

Cells gemified!

Friday, February 5th, 2010

We finally managed to push Cells to gemcutter, the key repository for Ruby gems.

Installing Cells is now as simple as

gem install cells

To load the gem in your Rails application you might extend your configuration in config/environment.rb:

Rails::Initializer.run do |config|
  config.gem "cells"

That’s all! Isn’t that great?

What did we do?

The question here is: What did Jonas Grimfelt do?

That’s this swedish guy who suddenly appeared in the project and brutally accelerated the gemify process with his incredible knowledge about gems, Rails plugins and conventions therefore.

Well, it was mostly him who

  • refactored the plugin to be a grown-up standalone gem that doesn’t need a daddy rails project
  • moved and tuned numerous files so they can be found by the autoloading
  • continuously urged me to fix all the tests
  • continuously urged me to fix things

The result is an enterprise cells gem. And the best: It’s even working!

Magic sucks – the new #render is explicit!

Thursday, December 24th, 2009

Having discussed the pros and cons thoroughly we finally decided to have an explicit #render in Cells.

Explicit code is the opposite of implicit – or magic – code. Evangelists of magic code often emphasize that their approach saves people from writing too much code. In place of user code, the library magically guesses what the programmer wants and invokes methods for him.

In Cells a state method usually worked by executing the state logic and then returning nil or calling #render.

def my_state
  do_something
  nil # instructs the outer method to automatically render my_state.html.
end

However, this #render was just a fake assignment and did not return the rendered view, as the name would imply. It just instructed the outer method to render the view. This is a perfect example for implicit code. You know that from the ActionController’s render cycle.

The new #render

When turning the old render cycle into an explicit mechanism we could throw away code. I claim that throwing away library code is a good thing.

User code will usually keep working.

This will work, since we return the rendered view.

def my_state
  render
end

Remember, #render really returns the markup for the view, so you might modify it.

def my_state
  markup = render
  „<p>+ markup +</p>end

Rendering your state view three times in a row is not a problem at all. No DoubleRenderError involved!

def my_state
  render + render + render
end

Even cooler, you can also use #render in your cell view, again. This replaces the obsolete concept of partials. We don’t treat partials in a special way in Cells anymore.

<p>
  We got <%= @count %> new users today.
  <%= render :view => 'top_user', :locals => {:user => @top_user} %>

Note that render :view => ... will respect view inheritance!

Here’s a short overview of more new features:

Did you know you can use layouts in your cell state? This could make your cell even more DRY.

render :layout => 'collapsable_widget'

Here, collapsable_widget.html would usually reside in app/cells/layouts.

In the former API you would just return a string as view. We now have the less magical :text parameter.

render :text =><p>Awesome stuff!</p>

Of course, this will work as well and you can save some markup.

render :text => „Awesome stuff!“, :layout => 'p_block'

For those who want the full power of templates without having templates.

render :inline => "<h1>Hey <%= @name %>!</h1>", :layout => 'page'

Maybe you want to render a complete new state on the cell instance. This would execute the state method and then return the rendered view within the current state.

def form
  setup_form
  @text_input = render :state => :text_field
 
  render
end
 
def text_field

Sometimes it’s handy to have local variables in the view.

render :locals => {:scoped_user => user_for_cell}

You can tell render which type of template you want, e.g. when distinguishing between request types.

render :template_format => :js

And sometimes it’s nice to simply shut up.

render :nothing => true

Have great holidays!

Cells for Rails 2.3 is out!

Saturday, March 28th, 2009

Cells bring back components to Rails, as superfast mini-controllers plugged into views or actions.

Just in time with the Rails 2.3 release cells got tagged 2.3 compatible. Thanks to some (great!) major changes in the Rails API we were able to throw away a LOT lines of code, configuration and thus make cells faster, cleaner and even easier to use. Here’s a short overview.

Built-in Engines support Engines are now an official part of the Rails core - meaning we can put cells inside engines/plugins and use them in our application as if they would reside in the global app/ directory. Even better:

No more configuration The tiresome task of configuring Rails working with cells is obsolete. You don’t have to touch config/environment.rb anymore. Especially you no longer need the lines

require File.join(File.dirname(__FILE__), '../vendor/plugins/cells/boot')

I18N support Use translation features in your cell views like the t("...") helper to provide localized versions of your application.

Automatic template lookup caching Cell template lookups (the filepaths of templates) are now cached like controller view lookups, providing automatic reloading in development mode and caching in production by using rails’ ActionView::Paths.

State output caching You can apply fine-grained output caching for each cell state. As soon as you declare a state as cached in the cell class, it won’t be executed the next time you render it. To re-render you can define a devalidation proc.

cache :some_state
cache :some_state,  Proc.new {|cell| false if cell.too_old?}

Download cells

Grab the plugin at github and also check out the example app demonstrating how to plug cells into your app and how to use advanced features like caching states and localized cell views.

Major refactorings in Rails 2.3 provide some clever new hooks for plugins. We loved hitting the delete key, getting rid of cells code and having a better cells as a result. Thanks and props to the rails core team!