With most of the pieces of the puzzle in place, I took today to go back over the codebase and remove artifacts of the refactoring work I've been doing, and spent some time renaming variables and methods I've created so they more accurately reflect what they're doing:
- ActionView::Template had a render method on it in which almost every line was an instance_variable_get or send() into ActionView::Base. I (slowly, very very slowly) moved the method over into ActionView::Base.
- Similarly, I moved the partial rendering code out of ActionView::RenderablePartial and onto ActionView::Base as well.
- I reorganized ActionView, creating directories for "render" and "template", and moving the appropriate files into the directories. This should significantly reduce the amount of visual clutter in the action_view base directory and make it easier to find the part of the code you're looking for.
- I was finally able to remove ActionView::Base#render_for_parts, which was the temporary shim I created when I started this round of refactoring to force all the callers into ActionView to call in with unified parameters. This was replaced with render_for_template yesterday (renamed to render_template_with_layout today), which means that the conduit between parts of ActionPack is now reduced to Template objects and layouts (also Template objects).
- The reorganization I referenced above also moved common methods into common files. For instance, the ActionView methods related to top-level rendering are in render/rendering.rb, while the ones related to rendering partials are in render/partials.rb.
On another note, I've been playing with an interesting memoization technique that lets you declare the methods to be memoized in a block:
class Foo extend Memoizable memoize do def memoed(baz) baz * 1000 end end def unmemoed(baz) baz * 1000 end end
After creating this class, Foo.new.memoed will be a memoized method, but creating the memoization will not use aliasmethodchain. Instead, it uses normal Ruby structures, and super. You can see the full details in a gist I posted with the code. It definitely gets a bit into the deep end of metaprogramming magic, but the end result is memoized methods that will retain their names in stack traces (probably my biggest personal gripe with aliasmethodchain).