Refactoring ActionView Template Handlers

I've been doing some deep digging around ActionView lately, and thought I'd clean some stuff up while I'm down there.

My first problem is ActionPack is really tightly coupled with ERB. My first instinct was to take advantage of the template handlers. I thought I could just refactor ERB, RJS, and Builder into nice TemplateHandlers and bind them with register_template_handler. Well, those template handlers are kind of second class because ActionView will not compile them into speedy templates.

I started working on it and I found a ton of other "dumb" things dropping out as well, like all this TEMPLATE_HANDLER_PREFERENCES non sense. My initial patch does alot of cleanup, but I'm asking for some feedback before I continue further.

http://dev.rubyonrails.org/ticket/10437

I think alot of the other template compile logic that is in ActiveView::Base private methods could be move over to the TemplateHandlers as well.

Looks great so far. And as you're already at it, probably you could look a bit into thread safety as well. That'd mainly be not to modify any class variables ( global behavior ) from any methods which are called while rendering, I suppose.

Nice work Josh! The beginning of a great and wondrous journey, I hope :wink:

Best, jeremy

I know it's already been committed, but just wanted to say that that is awesome work Josh!

Yeah, that's good thing to watch out for.

Thanks, I've been wanting to get around to this since this post (http://groups.google.com/group/rubyonrails-core/browse_thread/thread/ d1a1f92c94d7112e).

BTW, I'm not done. There is a few more things I had in mind. First clear all traces of "erb", "rjs", "builder", etc exceptions in ActionPack. Searching for those terms should only turn up results in there respective template handler. Also clean up my TODO notes that got committed :).

I'm also going try to move the compile template/caching stuff to another module so "base.rb" reads a bit cleaner.

Please post any other ideas yea got.

Awesome stuff, Josh.

The side effect is that you broke Haml, but I’m sure Haml guys will fix it tonight as they are aware of the change.

Here is to better ActionView!

  • Mislav

I looked at the HAML source before even starting this, and they don't even use the registered template handlers. They just override the render method. I think this will give them a better "official" way to patch in.

As a Haml guy, I guess I should chip in. This patch is a great step forward in terms of template delegation, which was always pretty awkward (hence the monkeypatching to get caching working).

However, it expects the template handlers to give a compiled Ruby string that's then rolled into a method by ActionView. Haml does produce such a string, but it's only dealt with internally, and it would be awkward to expose it directly for various reasons. What I'm using in the current monkeypatched code, and what I'd like to continue making use of, is Haml::Engine#def_method, which takes an object, a method name, and a list of local variables, and defines a method on the object with the given name that renders the template with those locals. It's pretty much identical to the work done by ActionView::Base#create_template_source, except it doesn't create the method name and it does evaluate the method definition.

If the source-generation/compilation stuff could be refactored out and made overridable by the individual template handlers, that would be ideal.

Otherwise, the main issue is that the Haml source has a non-standard line offset. If this could be set on a per-handler basis, instead of in ActionView::Base#compile_template, I could add a source accessor to Haml::Engine. But I'd rather not.

- Nathan

There any thoughts on Nathans email? I'm a happy hamler and hate to see haml left out here.

Yeah, I want really want to see what was need by other templates (HAML) before I moved to much into the TemplateHandler class. I tried to push all the template compiling stuff into the TemplateHandler class, so like you said, you could just override what you needed (But that failed on my first attempt). But please, give it a shot and see what else you can push into the TemplateHandler.