That's an interesting solution, in principle similar to the solution I 
had for the same problem.  However, there are some very un-Rails-ish 
statements in your tag implementation that make your intentions 
unclear.  For example, you find PageParts by their page_id, when really 
you should use the existing association:

  ancestor_part_names = ancestor.parts.map(&:name)

Next, you use Array.detect where include? will suffice:

  if ancestor_part_names.include?(layout_name)

Radiant's page model offers a shortcut method to getting a part by name, 
so your next detect call is also unneeded.  In fact this whole block of 
statements can be replaced by one line:

  tag.locals.page = ancestor if ancestor.part(layout_name)

Page#part will return nil if no matching part is found. Better yet, use 
find/detect instead of each:

tag.locals.page = page.ancestors.find {|p| p.part(layout_name) }

There are several other things in your tag definitions that could use 
attention, I'll probably make a pass at them later.

Sean

Witter Cheng wrote:
> 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.
>   

_______________________________________________
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