rails 3.1 template specific layouts via template resolver?
I've got a pretty straight forward template resolver returning templates from the database:
class MyResolver < ActionView::PathResolver
def query path, details, formats
template = MyTemplate.find_by_path path
...
ActionView::Template.new template.source, identifier, handler, details
end
end
That part works great... What I can't figure out is how to tell rails to use a layout associated with the templat开发者_StackOverflow中文版e that's been pulled from the database (i.e., template.layout_name or some such).
class MyResolver < ActionView::PathResolver
def query path, details, formats
template = MyTemplate.find_by_path path
layout template.layout_name # ??? yes? no?
ActionView::Template.new template.source, identifier, handler, details
end
end
Is there something I can call in the above query method to set the layout? Should I not be returning a ActionView::Template, but instead return my Template class with the appropriate AV::T methods included and then override some other part of the rendering stack and have that use template.layout_name?
You'd have to do something like this:
pages_controller.rb:
class PagesController < ApplicationController
prepend_view_path PageTemplate::Resolver.instance
def render_page
#Some logic to retrieve the @site & @current_page records....
render :layout => @site.layout.path, :template => @current_page.template.path
end
.
.
.
models/page_template.rb:
class Resolver < ActionView::Resolver
require "singleton"
include Singleton
def find_templates(name, prefix, partial, details)
if prefix.empty?
#If this is not a layout, look it up in the views table and pass that record to the init function
initialize_template('Template', record)
end
elsif prefix === 'layouts'
#If this is a layout, look it up in the layouts table and pass that record to the init function
initialize_template('Layout', record)
end
end
end
# Initialize an ActionView::Template object based on the record found.
def initialize_template(type, record)
source = record.body
identifier = "#{type} - #{record.id} - #{record.path.inspect}"
handler = ActionView::Template.registered_template_handler(record.handler)
details = {
:format => Mime[record.format],
:updated_at => record.updated_at,
:virtual_path => virtual_path(record.path, record.partial)
}
ActionView::Template.new(source, identifier, handler, details)
end
# Make paths as "users/user" become "users/_user" for partials.
def virtual_path(path, partial)
return path unless partial
if index = path.rindex("/")
path.insert(index + 1, "_")
else
"_#{path}"
end
end
end
Of course this can be refactored quite a bit, but this is the general idea. Also you would need 1 or 2 database tables depending weather you prefer to store the templates and layouts separately or together with the following columns: title, body, path, format, locale, handler, partial
Hope that helps!
精彩评论