# How to get a nice url hierarchy with slugs and acts\_as\_tree?

**URL:** <https://www.ruby-forum.com/t/how-to-get-a-nice-url-hierarchy-with-slugs-and-acts-as-tree/169209>\
**Category:** Rails\
**Created:** [May 31, 2009, 9:23pm UTC](https://www.ruby-forum.com/t/how-to-get-a-nice-url-hierarchy-with-slugs-and-acts-as-tree/169209 "2009-05-31T21:23:19Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![emmek](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/e/a698b9/32.png) [@emmek](https://www.ruby-forum.com/u/emmek)\
**Post date:** [May 31, 2009, 9:23pm UTC](https://www.ruby-forum.com/t/how-to-get-a-nice-url-hierarchy-with-slugs-and-acts-as-tree/169209/1 "2009-05-31T21:23:19Z")

</div>

I have a model Page in my application that acts\_as\_tree. I want this  
model to keep whole structure of website. I have some root nodes: home,  
contact, articles, etc. and the possibility of adding children to them.

I want to access these pages using slugs (Page model and new/edit forms  
have such attribute/field). In show action of pages controller:

```
if params[:slug]
  @page = Page.find_by_slug(params[:slug])
  raise ActiveRecord::RecordNotFound, "Page not found" if @page.nil?
else
  @page = Page.find(params[:id])
end

```

And routing:

map.connect ‘:slug’, :controller =\> ‘pages’, :action =\> ‘show’

Everything works well at the first level but how to access children  
pages using hierarchy of the tree and slugs?

Example structure:

Home (pages/1)  
Articles(pages/2)  
----Article1 (pages/5)  
----Article2 (pages/6)  
Contact(pages/3)  
About (pages/4)

I need this kind of access especially in ‘Articles’ node. I’d like to  
access several article using [mydomain.com/articles\_slug/article1\_slug](http://mydomain.com/articles_slug/article1_slug).

What is the nice way to do it? Could you post some helpful links or  
write solution? Any help appreciated.

---

<div class="post-metadata">

**Author:** ![emmek](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/e/a698b9/32.png) [@emmek](https://www.ruby-forum.com/u/emmek)\
**Post date:** [October 1, 2009, 6:48pm UTC](https://www.ruby-forum.com/t/how-to-get-a-nice-url-hierarchy-with-slugs-and-acts-as-tree/169209/2 "2009-10-01T18:48:16Z")

</div>

Hi Emmek,

I never found anything really convincing to handle that, but facing the  
same problem I found some workaround.

So first to get a slug, I use the plugin “ActsAsUrlParam”

> **[GitHub - caring/acts\_as\_url\_param: Pretty url support for Ruby on Rails...](https://github.com/caring/acts_as_url_param)**
>
> Pretty url support for Ruby on Rails applications. Contribute to caring/acts\_as\_url\_param development by creating an account on GitHub.

I use it on a page “model” that uses a custom acts\_as\_tree (with dotted  
ids, pretty convenient to boost performances)

> **[GitHub - xavier/acts-as-tree-with-dotted-ids: A drop in replacement for...](https://github.com/xavier/acts-as-tree-with-dotted-ids)**
>
> A drop in replacement for acts\_as\_tree with super fast ancestors and subtree access - GitHub - xavier/acts-as-tree-with-dotted-ids: A drop in replacement for acts\_as\_tree with super fast ancestors ...

Then I created special routes (yeah, to use with caution, I wanted to  
avoid the “/pages/” prefix )  
`
map.resources :pages
map.page_first_level ‘/:slug.:format’,
:controller=>:pages,:action=>:show
map.page_second_level ‘/:parent_slug/:slug.:format’,
:controller=>:pages,:action=>:show
map.page_third_level ‘/:ancestor_slug/:parent_slug/:slug.:format’,
:controller=>:pages,:action=>:show
`

finally in my page helper  
`
module PagesHelper
def smart_page_path(page,format=nil)
case page.depth
when 0
page_first_level_path(page.slug,:format=>format)
when 1
page_second_level_path(page.parent.slug,page.slug,:format=>format)
when 2
page_third_level_path(page.parent.parent.slug,
page.parent.slug,page.slug,:format=>format)
else
page_path(page)
end
end
end`

`
` it uses the page depth to generate my nice formatted URL

as result, using smart\_page\_path(@page)

-Home → /home.html  
-About → /about.html  
—History → /about/history.html  
—Team → /about/team.html  
-Projects → /projects.html  
—Global → /projects/global.html  
-----Ecology → /projects/global/ecology.html  
-----Human rights → /projects/global/human-rights.html  
—Local → /projects/local.html  
-Contact → /contact.html

BUT!!

- the extra params are just meant for SEO, you can use any routes, only  
the last slug will be used (/my-dummy-param/about.html)
- maybe it’s not that good to use routes that starts from the root… I  
always use an “admin” namespace fro my admin sections, so I never have  
much at the root anyway.

If someone has a better idea I’ll be delighted to hear it.

---

<div class="post-metadata">

**Author:** ![emmek](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/e/a698b9/32.png) [@emmek](https://www.ruby-forum.com/u/emmek)\
**Post date:** [October 1, 2009, 6:59pm UTC](https://www.ruby-forum.com/t/how-to-get-a-nice-url-hierarchy-with-slugs-and-acts-as-tree/169209/3 "2009-10-01T18:59:35Z")

</div>

Emmek on Rails wrote:

> I have a model Page in my application that acts\_as\_tree. I want this  
> model to keep whole structure of website.

Then I would strongly suggest awesome\_nested\_set instead of  
acts\_as\_tree. It makes it possible to use the DB _much_ more  
efficiently.

> I have some root nodes: home,  
> contact, articles, etc. and the possibility of adding children to them.
> 
> I want to access these pages using slugs (Page model and new/edit forms  
> have such attribute/field). In show action of pages controller:
> 
> ```
> if params[:slug]
> @page = Page.find_by_slug(params[:slug])
> raise ActiveRecord::RecordNotFound, "Page not found" if @page.nil?
> else
> @page = Page.find(params[:id])
> end
> 
> ```
> 
> And routing:
> 
> map.connect ‘:slug’, :controller =\> ‘pages’, :action =\> ‘show’
> 
> Everything works well at the first level but how to access children  
> pages using hierarchy of the tree and slugs?

I’m not sure. You might need to use a \*glob route for the page path,  
then do your own parsing.

## Best,

Marnen Laibow-Koser  
[http://www.marnen.org](http://www.marnen.org)  
removed\_email\_address@domain.invalid

---

<div class="post-metadata">

**Author:** ![emmek](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/e/a698b9/32.png) [@emmek](https://www.ruby-forum.com/u/emmek)\
**Post date:** [October 1, 2009, 7:02pm UTC](https://www.ruby-forum.com/t/how-to-get-a-nice-url-hierarchy-with-slugs-and-acts-as-tree/169209/4 "2009-10-01T19:02:31Z")

</div>

Marnen Laibow-Koser wrote:

> Emmek on Rails wrote:
> 
> > I have a model Page in my application that acts\_as\_tree. I want this  
> > model to keep whole structure of website.
> 
> Then I would strongly suggest awesome\_nested\_set instead of  
> acts\_as\_tree. It makes it possible to use the DB _much_ more  
> efficiently.

Actually, on second thought, this might be a good use case for a  
materialized path in the DB. Then you could just do find\_by\_path to  
retrieve any page at any depth.

## Best,

Marnen Laibow-Koser  
[http://www.marnen.org](http://www.marnen.org)  
removed\_email\_address@domain.invalid
