开发者

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!

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜