I have revived this post in order to get comments on my implementation 
of nested layouts.  I created custom tags to allow for this.  Here is my 
solution to the scenario given above.

First, in "/", create a page part called "layout" to be used as the 
nested layout.  It will look like this:

<r:layout_part name="left">
<div class="left">
<r:content part="left" />
</div>
</r:layout_part>

<r:layout_part name="main">
<div class="main">
<r:content part="main" />
</div>
</r:layout_part>

Then edit the "body" page part of "page1" and "page2" to look like this:

<r:layout />

The code behind r:layout and r:layout_part follows:

---------------------

    # the layout is actually a page part
    # if the named page part is not a part of the current page
    # ancestors are searched until the named page part is found
    tag 'layout' do |tag|
        ret_val = ""
        layout_name = tag.attr['layout_name'] || "layout"
        page = tag.locals.page
        page_part_names = 
page.instance_variable_get(:@parts).collect(&:name)
        parts_for_layout = tag.attr['parts'] || 
page_part_names.delete_if{|part| part == "body" || part == layout_name }
        found = nil
        og_page_id = page.id
        if !page_part_names.include? layout_name
            page.ancestors.each do |ancestor|
                pp = 
PagePart.find_all_by_page_id(ancestor.instance_variable_get(:@attributes)["id"],
 
:include => [:page])
                ancestor_part_names = pp.collect(&:name)
                if ancestor_part_names.detect{|part| part == layout_name 
} && !found
                    tag.locals.page = pp.detect{|p| p.name == 
layout_name}.page
                    found = 1
                end
            end
            tag.render('content', {"part" => layout_name, 
"parts_page_id" => og_page_id})
        else
            tag.render('content', {"part" => layout_name})
        end
    end

    tag 'layout_part' do |tag|
        part_to_render = tag.attr['name']

        # this mess is necessary; trying to get tag_binding_stack 
directly from the context returns a different array
        page = tag.locals.page
        response = page.instance_variable_get(:@response)
        template = response.instance_variable_get(:@template)
        controller = template.instance_variable_get(:@controller)
        pagee = controller.instance_variable_get(:@page)
        context = pagee.instance_variable_get(:@context)
        tbs = context.instance_variable_get(:@tag_binding_stack)

        parts_page_id = tbs.last.attributes["parts_page_id"]

        # if the layout is in the same page as the parts being laid out
        # the parts_page_id will not have been specified, so do not 
reset the tag page
        unless parts_page_id.blank?
            parts_page = Page.find(parts_page_id)
            tag.locals.page = parts_page
        end

        # e.g. name of part is specified in the tag as 'blah'
        # but the page calling the layout tag which wraps this tag does 
not have a 'blah' part
        # in such a case don't display this tag
        # NOTE: there is likely a more efficient way to do this check 
than a db query
        pp = PagePart.find_by_name_and_page_id(part_to_render, 
parts_page_id || tag.locals.page.id)
        tag.expand unless pp.blank?
    end


---------------------

Thank you in advance for any criticism/comments.
-- 
Posted via http://www.ruby-forum.com/.
_______________________________________________
Radiant mailing list
Post:   [email protected]
Search: http://radiantcms.org/mailing-list/search/
Site:   http://lists.radiantcms.org/mailman/listinfo/radiant

Reply via email to