Forum: Ruby on Rails Acts_as_tree and routing

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Alex Y. (Guest)
on 2005-12-15 15:48
(Received via mailing list)
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,
Duane J. (Guest)
on 2005-12-15 16:27
(Received via mailing list)
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...
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)
Alex Y. (Guest)
on 2005-12-15 16:35
(Received via mailing list)
Duane J. wrote:
>
> On Dec 15, 2005, at 6:40 AM, Alex Y. wrote:
<snip>
> Alex,
>
> Check this page out:
> 
http://blog.chanezon.com/articles/2005/05/20/rails...
>
> 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)
<snip>
>   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,
Duane J. (Guest)
on 2005-12-15 17:03
(Received via mailing list)
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)
Alex Y. (Guest)
on 2005-12-15 18:15
(Received via mailing list)
Duane J. wrote:
>>> Check this page out: 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,
This topic is locked and can not be replied to.