B4ec694f9d955bee753559037aa1805a

I have something, working related to the title, however i wanted to get a second opinion. I am
trying to create a manageable site navigation system using better_nested_set.

Primary level navigation:
is static to the user, and will not be manageable.
Secondary level navigation:
can be added to any primary level navs.
can be sortable
Tertiary level navigation:
can be added to any secondary level navs.
can be sortable.

Using Scriptaculous I wanted to be able and sort the Secondary and Tertiary nav items.
The following works, but leaves me again wonder if there is a better way.

If nothing else this post should be a little helpful for those using better_nested_set for a dynamic navigation.

<%= link_to 'New page', new_page_path %>

<div id="items">
<ul id='page-tree' >
<% for primary_page in @all_top_level_pages %>

	<li id="<%= primary_page.dom_id %>">
		
		<%= primary_page.title %><%= link_to "(+)", :action => "new",  :id => primary_page%>
		<%-if  primary_page.children? %>
			<ul class="edit_list">
				<% for secondary_page in primary_page.children %>
					<li id="<%= secondary_page.dom_id %>">
						
						<%= secondary_page.title %><%= link_to "(+)", :action => "new",  :id => secondary_page%>
						<%- if  secondary_page.children? %>
						
							<ul id="sortable_list_<%= secondary_page.dom_id %>">
								<% for tertiary_page in secondary_page.children %>
									<li id="<%= tertiary_page.dom_id %>"><%= tertiary_page.title %></li>
						
								<%- end -%>	
							</ul>
							<%= sortable_element("sortable_list_#{secondary_page.dom_id}", 
							 						:url => {:action => 'update_positions', 
															:id => "sortable_list_#{secondary_page.dom_id}"}) %>
						<% end %>
					</li>
				<%- end -%>
			</ul>
		<%- end -%>
	</li>
<% end %>
</ul>

</div>
class PagesController < ApplicationController

def update_positions
  # returned array contains the Page ids
  Page.reorder_siblings(params[params[:id]])
  @all_top_level_pages = Page.all_top_level_pages
end

  def index
    @pages = Page.find(:all)
    @all_top_level_pages = Page.all_top_level_pages
    respond_to do |format|
      format.html # index.html.erb
      format.xml  { render :xml => @pages }
    end
  end
end
# == Schema Information
# Schema version: 20080905194928
#
# Table name: pages
#
#  id         :integer(11)     not null, primary key
#  title      :string(255)     
#  summary    :string(255)     
#  body       :text            
#  parent_id  :integer(11)     
#  lft        :integer(11)     
#  rgt        :integer(11)     
#  created_at :datetime        
#  updated_at :datetime        
#
class Page < ActiveRecord::Base
  acts_as_nested_set

  attr_accessor :child_of
  def self.all_top_level_pages
    Page.find(:all, :conditions => "parent_id = 1")
  end
  
  def self.reorder_siblings(siblings)

    index = 0
    @parent = nil
    last_child = nil

    # Heres were most of the work is done
    siblings.each do |child|
      this_child = Page.find(child)
      
      # If last child is nil, then we know that we are dealing with the first item
      # in the array
      if(last_child.nil?)
          last_child ||= this_child
      else
        # If we are here the we know that we need to take this child and 
        # move it to the right of the last child
          this_child.move_to_right_of last_child
          last_child = this_child
      end
    end
  end
end

Refactorings

No refactoring yet !

F288a8afe5302a16a366d5e9d34f2fec

Joe Grossberg

September 11, 2008, September 11, 2008 15:32, permalink

No rating. Login to rate!

Not a refactoring, but three comments:
* are you certain all those LI id's are going to be unique? Otherwise, they're not valid HTML.
* you should split that view into partials, for readability
* if you're getting to the level or tertiary, you're probably trying to fit too much into your navigation; it's a UI "smell"

B4ec694f9d955bee753559037aa1805a

nathan

September 11, 2008, September 11, 2008 16:21, permalink

No rating. Login to rate!

Thanks you so much for taking the time to respond. I am certain that the li tags will be unique. If by some chance they were to collide, I would have bigger issues then valid html,, like bad data.
Your right, the tree should be put in to a partial. I have done that this morning.
I agree with you about the UI smell, but unfortunately I have no say in the navigation rules.
I just have to make it work.

Thank you so much Joe! I plan to post later my own refactoring results.

A239cece7a08db0ba8b7f790fa4f62ff

Nate

October 3, 2008, October 03, 2008 02:27, permalink

No rating. Login to rate!

This looks like a damn decent code snippet. Could I ask for a screenshot of how you have implemented it or of a basic implementation, just so that I can see how it looks? Also, could I please get permission to put this into a CMS project I am working on? Cheers. Nate

Your refactoring





Format Copy from initial code

or Cancel