It is common in Rails 3.0 applications that you want to provide default views for a group of controllers. Let’s say you have a bunch of controllers inside the Admin namespace and you would like each action to fallback to a default template. So if you are rendering the index action for Admin::PostsController and “app/views/admin/posts/index.html.*” is not available, it should then render “app/views/admin/defaults/index.html”.
There are several ways to implement this feature at the controller level. It mainly relies on trying to render the original template and then rescue ActionView::MissingTemplate. If this error is rescued, you then render the default one. However, there is a considerable performance overhead in this approach as it needs to pass through the rendering and template lookup stack twice.
Luckily, since Rails 3.0, we have a new abstraction called resolvers that holds the logic to find a template. I explain comprehensively how resolvers work and their API in my book Crafting Rails Applications. So here I would just show the basics to get this functionality working.
First, we need to define a DefaultResolver, it could be done inside the lib directory:
class MyResolver < ::ActionView::FileSystemResolver def initialize super("app/views") end def find_templates(name, prefix, partial, details) super(name, "admin/defaults", partial, details) end end |
Our new resolver simply inherits from ActionView::FileSystemResolver and does two changes: Overrides the initialize method so the view path defaults to “app/views” inside our application and overrides find_templates. The find_templates method receives the template name, a prefix (i.e. the controller path), a boolean marking if the template is a partial or not and a hash of details. In the example above, we simply ignore the prefix given and hardcode it to “admin/defaults”.
Now, assuming that all controllers inside the Admin namespace inherit from an Admin::ApplicationController, we can add default views to all of them by adding the following line:
class Admin::ApplicationController < ActionController::Base append_view_path MyResolver.new end |
And we are done! The view_paths holds a list of paths and/or resolvers that the controller will look for templates until one is found. If none is found, an ActionView::MissingTemplate is raised. Since we used append_view_paths, our resolver was added after the “app/views” path, used by default in all controllers.
As you may have guessed, resolvers are a powerful abstraction that allows you to retrieve templates from anywhere, including the database, which is the example given in Crafting Rails Applications.
Finally, template inheritance was a feature recently added to Rails master (upcoming Rails 3.1), so you won’t need to create your custom resolver as above. There is a good wrap up about this feature in Rails Edge.
Tags: crafting rails applications, rails 3, rails 3.1, resolvers, template inheritance
This entry was posted on Monday, April 4th, 2011 at 3:00 pm and is filed under English. You can follow any responses to this entry through the RSS 2.0 feed. Both comments and pings are currently closed.-
http://twitter.com/brmichel Bruno Michel
-
http://blog.plataformatec.com.br/ josevalim
-
http://blog.plataformatec.com.br/ josevalim

All
English only
Em português apenas