Magic sucks – the new #render is explicit!
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!
December 27th, 2009 at 4:15 pm
Looks great. Especially rendering partials and implementing layouts within your cell views.
December 27th, 2009 at 4:19 pm
Yes! Much prefer explicit render over implicit. Look forward to using it soon!
December 30th, 2009 at 4:26 pm
Awesome work on the upgrades Nick! I’m looking forward to using these new features. Now I can tick that off my Christmas wish list!
Thanks man.
December 30th, 2009 at 10:55 pm
This new API is a big improvement in my opinion. A win for the Principle Of Least Suprise! Cells is growing up to be a worthy Rails replacement for Merb Parts. Thanks Nick!
December 30th, 2009 at 11:08 pm
Anyone starting in Ruby on Rails today should really start at the top, at Apotomo.
Thank You for your brilliant widgets works, Nick.