Yehuda Katz is a member of the Ruby on Rails core team, and lead developer of the Merb project. He is a member of the jQuery Core Team, and a core contributor to DataMapper. He contributes to many open source projects, like Rubinius and Johnson, and works on some he created himself, like Thor.
Today’s Communique
January 7th, 2009
During work today, I made more progress in unifying the ActionController=>ActionView API:
The API into ActionView is now ActionView::Base#_render_for_template. This is where the refactor was going all along, and with Josh’s help, we were able to really solidify how this should work.
At the moment, there are a few stragglers that may or may not be cleaned up: AV::Base#_render_text and AV::Base#_render_inline. Using _render_inline in particular ensures that render :inline does the same thing in both ActionController and ActionView. This is the code in ActionController that delegates to ActionView for :inline:
if inline = options[:inline] render_for_text(@template._render_inline(inline, _pick_layout(layout_name), options))
This is the code in ActionView for rendering inline:
elsif inline = options[:inline] _render_inline(inline, layout, options)
As you can see, having a single method allows us to be sure that the code does the same thing in both places. You can compare with the code from before the refactor. ActionController:
elsif inline = options[:inline] render_for_text(@template.render(options.merge(:layout => layout)), options[:status])
ActionView:
elsif options[:inline] InlineTemplate.new(options[:inline], options[:type]).render(self, options[:locals])
Not particularly terrible, but the mechanism is a bit more obscure, and it’s less obvious that both pieces of code do the same thing. Before the refactor, you can see that ActionController delegated to ActionView’s render method, after twiddling with the options and passing them through uncritically.
Another interesting item in today’s refactor: previously, layout selection happened at the beginning of the render method, before the options were examined. As a result, it was necessary for the template chooser to scan through all the options to determine whether it should fall back to the default layout if no layout was specified. For instance, render :action assumes that a layout should be used by default, while render :text assumes that a layout should not be used. Of course, :layout => “…” can be specified, but the default behavior is different.
In the refactored version, the _pick_layout method is called with information about whether it should fall back to the default, so it no longer has to scan the options. It also means that a layout is never selected if it is not required (render :nothing or RJS, for instance).
After work, I hung out with a friend from New York, but when I got back I decided to do a bit more work on Rails.
Some interesting stuff: I’m experimenting with ConcurrentHash and SafelyMemoizable, which exploits the fact that Ruby implicitly locks instance variable mutations to create a cache that should both be threadsafe and not require locks for almost all cases. This also allows a very simple threadsafe memoization technique for global caches. Again, this is a pretty early experiment, so the details may change some. Note that it’s not as expensive as it looks, because Hash#dup is a shallow clone, so the memory-expensive values will exist only once in memory.
I also cleaned up layouts a bit more, including replacing a somewhat complex mechanism for dealing with default layouts that was implemented via an inherited hook that involved the rules for whether or not a missing layout should raise an error. It still is fairly arcane stuff, but I’m pretty pleased with the revised code. I needed to add some tests for layout :except and layout :only, as there were no tests for that functionality.
The very last thing tonight was to put the final piece in place to have a single place for determining whether a response is exempt from layout. Now that all options that involve rendering templates go through the same method, all of the logic for skipping layout is encapsulated in layout = _pick_layout(*layout) unless tmp.exempt_from_layout?. Putting this piece in place was very personally satisfying.
At this point, I’m pretty sure I’m posting simply to create a personal record of my work. If some of you are enjoying it, that’s a bonus!

Luke Melia, Posted January 7, 2009, 6:23 am
> At this point, I’m pretty sure I’m posting
> simply to create a personal record of my
> work. If some of you are enjoying it, that’s
> a bonus!
These are some of my favorite blog posts of the last few weeks. It’s very helpful to have the background while doing something like fixing plugin interactions.
On that note, I looked at making active_scaffold compatible with edge rails at the request of a colleague a few days ago, and found that it was a vastly cleaner and easier to integrate with ActionView than it was prior to the recent refactorings. Great work.
Nick, Posted January 7, 2009, 6:26 am
Fascinating to read how you’re approaching this. Keep it up!
José Valim, Posted January 7, 2009, 6:52 am
I’m quite interested in your work’s personal record! =)
Just one question: on SafelyMemoizable you have to write the “memoized_method” and safely_memoized is the one who actually creates the method you want to memoize. I found it cleaner and better than Rails current memoize implementation because less is happening behind the scenes. So, any plans to move this implementation to memoize also?
aleco, Posted January 7, 2009, 9:10 am
Yehuda, I’ve been using Rails for 18 months now and never really managed to understand its internals. But with your daily progress report I’m finally able to grasp what’s going on behind the scenes, which is why I’m very thankful for both your work and your posts. Please don’t stop.
Jonathan Hicks, Posted January 7, 2009, 10:03 am
It great to hear about the progress being made towards Rails 3.0. I, for one, really appreciate the updates you give. I also look into the rails code more so maybe in the future I can help contribute as well. Keep up the good work!
Luke Randall, Posted January 7, 2009, 11:21 am
I thoroughly enjoy reading your updates, so please keep it up! I’m amazed at the volume of work you are able to get through each day…
Elliot Temple, Posted January 7, 2009, 1:09 pm
I like your posts a lot.
Yehuda Katz, Posted January 7, 2009, 2:02 pm
@jose I personally like it, but it would be a breaking API change. I personally think that being explicit in this case is a win (especially when tracking down bugs in stack traces).
José Valim, Posted January 7, 2009, 4:18 pm
@yehuda yes, it’s an API change, but by checking if the memoized_method exists we can make both implementations “live together” in the same call and then we could just add a deprecation warning =)
ps: this just remembered me of one of the current options in Rails’ UserVoice page:
http://rails.uservoice.com/pages/rails3/suggestions/98512-have-less-overly-clever-code-in-the-core
Jay Levitt, Posted January 8, 2009, 10:40 am
Another 1 for the posts. Even if I don’t fully understand them now (because I’m not following along with the source code), they’ll be invaluable in six months when somebody wants to know why on earth something changed to something else. They’re great search fodder.