Acts_as_tree and routing


#1

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,


#2

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-
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)


#3

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)


#4

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 :slight_smile:

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,


#5

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

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,