# Acts\_as\_tree and routing

**URL:** <https://www.ruby-forum.com/t/acts-as-tree-and-routing/50341>\
**Category:** Rails\
**Created:** [December 15, 2005, 2:48pm UTC](https://www.ruby-forum.com/t/acts-as-tree-and-routing/50341 "2005-12-15T14:48:28Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![regularfry](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/45deac/32.png) [@regularfry](https://www.ruby-forum.com/u/regularfry)\
**Post date:** [December 15, 2005, 2:48pm UTC](https://www.ruby-forum.com/t/acts-as-tree-and-routing/50341/1 "2005-12-15T14:48:28Z")

</div>

I’ve got an acts\_as\_tree structure which I want to be able to represent  
in the URL, with one field identified as the url component. In other  
words, if I’ve got this:

def self.up  
create\_table :nodes do |t|  
t.column :parent\_id, :integer  
t.column :tag, :string  
end  
end

and

class Node \< ActiveRecord::Base  
acts\_as\_tree  
end

and what I want the urls to be is something like:

map.connect ‘node/view/\*tag’, /_somethingIdon’tknowhere_/

what’s the easiest way to make this work, assuming that I can validate  
that no two siblings have the same tag? It doesn’t seem that unusual a  
requirement, but I can’t see any documentation for this sort of  
arrangement anywhere.

Thanks,

---

<div class="post-metadata">

**Author:** ![regularfry](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/45deac/32.png) [@regularfry](https://www.ruby-forum.com/u/regularfry)\
**Post date:** [December 15, 2005, 3:27pm UTC](https://www.ruby-forum.com/t/acts-as-tree-and-routing/50341/2 "2005-12-15T15:27:42Z")

</div>

On Dec 15, 2005, at 6:40 AM, Alex Y. wrote:

> what’s the easiest way to make this work, assuming that I can  
> validate that no two siblings have the same tag? It doesn’t seem  
> that unusual a requirement, but I can’t see any documentation for  
> this sort of arrangement anywhere.
> 
> ## Thanks,
> 
> Alex

Alex,

Check this page out:  
[http://blog.chanezon.com/articles/2005/05/20/rails-tip-create-a-route-](http://blog.chanezon.com/articles/2005/05/20/rails-tip-create-a-route-)  
with-an-arbitrary-number-of-parameters

It seems to be what you’re looking for.

Also, I would suggest making a method similar to this one in your  
model for easy conversion of a path to an array of nodes:

def self.to\_chain(path)  
node\_names = path.is\_a?(String) ? path.split(‘.’) : path

```
 links = []
 parent_id = node = nil
 for name in node_names
   node = Node.find_by_tag_and_parent_id(name, parent_id)
   if node.nil?
     links = nil
     break
   end
   links << node
   parent_id = node.id
 end
 links

```

end

Then in your controller:  
before\_filter :set\_node

def set\_node  
chain = Tag.to\_chain(params[:tag])  
@node = chain.last unless chain.nil?  
end

Duane J.  
(canadaduane)

---

<div class="post-metadata">

**Author:** ![regularfry](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/45deac/32.png) [@regularfry](https://www.ruby-forum.com/u/regularfry)\
**Post date:** [December 15, 2005, 4:03pm UTC](https://www.ruby-forum.com/t/acts-as-tree-and-routing/50341/3 "2005-12-15T16:03:10Z")

</div>

On Dec 15, 2005, at 7:28 AM, Alex Y. wrote:

> 

The route generator will not do recursive things like that. You’ll  
need to make your own ‘url\_for’ helper method that generates a string  
path, e.g.:

def path\_to(node, prefix = ‘node/’)  
prefix + node.chain.join(’/’)  
end

(the ‘chain’ method is a custom method that returns an array  
containing each Node object from the given node to the root of the tree)

Then something like this wouldn’t be too messy: \<%= link\_to ‘click  
here’, path\_to(@current\_node) %\>

Duane J.  
(canadaduane)

---

<div class="post-metadata">

**Author:** ![regularfry](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/45deac/32.png) [@regularfry](https://www.ruby-forum.com/u/regularfry)\
**Post date:** [December 15, 2005, 5:15pm UTC](https://www.ruby-forum.com/t/acts-as-tree-and-routing/50341/4 "2005-12-15T17:15:30Z")

</div>

Duane J. wrote:

> > > Check this page out: [http://blog.chanezon.com/articles/2005/05/20/](http://blog.chanezon.com/articles/2005/05/20/)  
> > > path, e.g.:  
> > > Bah. I thought it’d be something like that 🙂

> def path\_to(node, prefix = ‘node/’)  
> prefix + node.chain.join(‘/’)  
> end
> 
> (the ‘chain’ method is a custom method that returns an array containing  
> each Node object from the given node to the root of the tree)  
> In this case, it’s an acts\_as\_tree, so I can do something convenient  
> with node.ancestors.

Thanks anyway,

---

<div class="post-metadata">

**Author:** ![regularfry](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/45deac/32.png) [@regularfry](https://www.ruby-forum.com/u/regularfry)\
**Post date:** [December 15, 2005, 3:35pm UTC](https://www.ruby-forum.com/t/acts-as-tree-and-routing/50341/5 "2005-12-15T15:35:57Z")

</div>

Duane J. wrote:

> On Dec 15, 2005, at 6:40 AM, Alex Y. wrote:  
>   
> Alex,
> 
> Check this page out:  
> [http://blog.chanezon.com/articles/2005/05/20/rails-tip-create-a-route-with-an-arbitrary-number-of-parameters](http://blog.chanezon.com/articles/2005/05/20/rails-tip-create-a-route-with-an-arbitrary-number-of-parameters)
> 
> It seems to be what you’re looking for.  
> I saw that, but it’s not obvious at all how to make it work for the  
> url\_for functions. Will I have to just bodge it each time, or is there  
> a nice way of making it generate the \*tag portion automatically?

> Also, I would suggest making a method similar to this one in your model  
> for easy conversion of a path to an array of nodes:
> 
> def self.to\_chain(path)  
>   
> end
> 
> Then in your controller:  
> before\_filter :set\_node
> 
> def set\_node  
> chain = Tag.to\_chain(params[:tag])  
> @node = chain.last unless chain.nil?  
> end  
> I’ve got something similar to that already, but I didn’t put it in a  
> before\_filter because the structure’s only used for a single method at  
> the moment.

Thanks,
