SitePoint Sponsor

User Tag List

Results 1 to 5 of 5

Hybrid View

  1. #1
    SitePoint Member
    Join Date
    Feb 2008
    Posts
    3
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    acts_as_tree: Sorting by full ancestry

    I'm new to RoR, and I'm having trouble sorting a list of categories using acts_as_tree. Specifically, my list produces something like:

    History > Modern > 20th Century
    History > United States > 20th Century
    Juvenile Fiction > Historical > United States > 20th Century
    Juvenile Non-Fiction > History > United States > 20th Century
    History > Modern > 21st Century
    That's because I'm sorting by "name," rather than the full ancestry plus the name. What I would like to do is produce a list like this:


    History > Modern > 20th Century
    History > Modern > 21st Century
    History > United States > 20th Century
    Juvenile Fiction > Historical > United States > 20th Century
    Juvenile Non-Fiction > History > United States > 20th Century
    For the life of me, I can't figure out how to sort on the "long name" (ancestry + name). Everything I try seems to error out.

    For background information, my model looks like this:

    class Category < ActiveRecord::Base
    acts_as_tree

    def ancestors_name
    if parent
    parent.ancestors_name + parent.name + ' > '
    else
    ""
    end
    end

    def long_name
    ancestors_name + name
    end

    end

    The pertinent parts of my controller look like this:

    class CategoriesController < ApplicationController

    def list
    @all_categories = Category.find(:all, :order => "name")
    end
    And the list.rhtml (view) looks like this:

    <h1>Listing categories</h1>

    <table>
    <tr>
    <th>Name</th>
    </tr>

    <% for category in @all_categories %>
    <tr>
    <td><%=h category.long_name %></td>
    <td><%= link_to 'Edit', :action => 'edit', :id => category %></td>
    <td><%= link_to 'Destroy', { :action => 'destroy', :id => category }, :confirm => 'Are you sure?', :method => :post %></td>
    </tr>
    <% end %>
    </table>

    <br />

    <%= link_to 'New category', :action => 'new' %>
    Of course, I would like to do a lot more with this than just the list, but if I can figure out how to do the list, I should be able to figure out the rest.

    Any help would be most appreciated!

  2. #2
    SitePoint Enthusiast AllTom's Avatar
    Join Date
    Feb 2008
    Location
    Wherever danger lies...
    Posts
    48
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I would sort them after they've been returned from the database.

    Code Ruby:
    @all_categories = Category.find(:all).sort_by { |c| c.ancestors_name }

    If this actually proves inefficient (you're sorting a ton of categories), you can try some of the various optimizations in the documentation for sort_by. I just don't know an easy way to do this with SQL or via ActiveRecord.

  3. #3
    SitePoint Member
    Join Date
    Feb 2008
    Posts
    3
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    A little further along, but not there

    Thanks, AllTOM, but that fix sorts by the number of levels in the ancestry, not the total string. For instance, I get something like:

    History
    Juvenile Fiction
    Juvenile Non-Fiction
    History > Modern
    History > United States
    Juvenile Fiction > Historical
    Juvenile Non-Fiction > History
    History > Modern > 20th Century
    History > Modern > 21st Century
    History > United States > 20th Century
    Juvenile Fiction > Historical > United States
    Juvenile Non-Fiction > History > United States
    Juvenile Fiction > Historical > United States > 20th Century
    Juvenile Non-Fiction >History > United States > 20th Century

    when what I want is:

    History
    History > Modern
    History > Modern > 20th Century
    History > Modern > 21st Century
    History > United States
    History > United States > 20th Century
    Juvenile Fiction
    Juvenile Fiction > Historical
    Juvenile Fiction > Historical > United States
    Juvenile Fiction > Historical > United States > 20th Century
    Juvenile Non-Fiction
    Juvenile Non-Fiction > History
    Juvenile Non-Fiction > History > United States
    Juvenile Non-Fiction > History > United States > 20th Century
    This is quite a conundrum, but it seems like it is such an everyday task. When dealing with multiple levels of categories, it seems like the second listing is what you'd always want to do, yet no one seems to have developed an easy way to do it. One would think that RorR, with its emphasis on making everyday tasks easier would have come up with a solution.

    Somehow, I think the resolution must lie in turning the whole "long_name" into a string and sorting that, but I just don't know enough RoR to do that. (Or come up with a better way.)

    LarryTX

  4. #4
    SitePoint Enthusiast AllTom's Avatar
    Join Date
    Feb 2008
    Location
    Wherever danger lies...
    Posts
    48
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Does it work if you change my "ancestors_name" to "long_name"? (My error there...)

    sort_by uses the values you return in the block as the keys by which to sort, just as you describe in the last paragraph of your post.

    It would be a little tedious for me to recreate your data on my end to try it, but using long_name where I wrote ancestors_name seems like it would work.

  5. #5
    SitePoint Member
    Join Date
    Feb 2008
    Posts
    3
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Works Perfectly!

    Thanks a million, AllTom! That worked perfectly. I've been working on this one in PHP for quite some time, and (with what seemed like thousands of lines of code) never got it to work. I tried RoR as an alternative.

    Although I must say that the transition from PHP is not an easy one (I feel like someone who's just gone from an Olympic swimmer to not being able to tread water.), I think you just might have a convert to RoR.

    LarryTX


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •