Magic sucks – the new #render is explicit!
Thursday, December 24th, 2009Having 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!