Nested routing in Ruby on Rails
Asked Answered
G

4

7

My model class is:

class Category < ActiveRecord::Base
  acts_as_nested_set
  has_many :children, :foreign_key => "parent_id", :class_name => 'Category'
  belongs_to :parent, :foreign_key => "parent_id", :class_name => 'Category' 


  def to_param
    slug
  end
end

Is it possible to have such recursive route like this: /root_category_slug/child_category_slug/child_of_a_child_category_slug ... and so one

Thank you for any help :)

Guzel answered 1/4, 2010 at 8:30 Comment(0)
S
4

You can do that with regular routes and Route Globbing, so for example,

map.connect 'categories/*slugs', :controller => 'categories', :action => 'show_deeply_nested_category'

Then in your controller

def show_deeply_nested_category
  do_something = params[:slugs]  # contains an array of the path segments
end

However, note that nested resource routing more than one level deep isn't recommended.

Soble answered 4/4, 2010 at 2:56 Comment(3)
I had the same question, and this works perfectly. I would argue Jamis' rule doesn't apply in this case, since the resource itself is represented as a hierarchical structure. (And there's no need to use nested resources/routes in this case anyway).Bombazine
I had to use 'match' instead of 'map.connect' and it worked perfectlyVelocity
What should be done as an alternative to nesting more than one deep? The documentation doesn't say.Confiscatory
B
2

I doubt it, and it's not a good idea. Rails Route mapping code is complex enough without having to dynamically try to encode & decode (possibly) infinite route strings.

Boggess answered 4/4, 2010 at 2:12 Comment(0)
W
1

You can use constraints in rails routing. eg:

match '*id', :to => 'categories#show', :constraints => TaxonConstraint.new

class TaxonConstraint
  def matches?(request)
    path = request.path.slice(1..(request.path.length-1)
    path = path.split('/')
    return false if path.length != path.uniq.length
    return true if Category.check(path.last).first
    false
  end
end

class splits your path by "/" , and checks db for last element in db. if not found, skips the route. if any one knows, how to solve it better, would be glad to hear.

Workhorse answered 29/7, 2011 at 8:13 Comment(1)
heh, i found best solution. then create new category with acts_as_nested_set, you can generate path to root in 1 query. and then just check field "path" => "a/b/c".Workhorse
M
0

It's not easy (read: I don't know how to do it) and it's not advised. Imagine if you have 10 categories, you do not want the url to be /categorya/categoryb/categoryc/categoryd/categorye/categoryf/categoryg/categoryh/categoryi/categoryj.

Perhaps a maximum level of 3 would grant you the power you desire, without polluting the URL?

Madonia answered 1/4, 2010 at 10:46 Comment(2)
For my opinion level the level should be limited by the model, not by the routing rule.Guzel
@Ryan Bigg, how would you prefer to write a URL for something like this, assuming you do have n-depth? he's trying to show a category in a certain location in the tree (and it could have others).Essentialism

© 2022 - 2024 — McMap. All rights reserved.