Search code examples
ruby-on-railslink-to

The link_to function does not display correctly the links from an array


I have a rails 2.3 application where I defined my routes like this:

map.connect ':controller/:level1/:level2', :action => 'index'
map.connect ':controller/:level1',         :action => 'index'

I want to make some links like a breadcrumb, depending on the page I'm in. For example, suppose my controller name would be 'contr', if my path is /contr, there would be only one link: '/contr'. If my path would be '/contr/level1/level2', I would like to have 3 links: '/contr', '/contr/level1' and '/contr/level1/level2'.

Here is how I tried:

In my view I detect these levels:

b_titles = []
b_links = []
b_titles << 'Contr'
b_links  << ({:controller=>'contr'})
if !params[:level1].nil?
  b_titles << 'Level 1'
  b_links << ({:controller=>'contr', :level1=> params[:level1]})
  if !params[:level2].nil?
    b_titles << 'Level 2'
    b_links << ({:controller=>'contr', :level1=> params[:level1], :level2=>params[:level2]})
  end
end

After I make these arrays, I test them using function p

p b_links
p b_titles

and in console there are the desired results:

[{:controller=>"contr"}, {:level1=>"level1", :controller=>"contr"}, {:level1=>"level1", :level2=>"level2", :controller=>"contr"}]
["Contr", "Level 1", "Level 2"]

Now I want to make a list of links for the breadcrumb:

<% b_titles.each_with_index do |title, i| %>
    <%= link_to(title, (b_links[i]))  %>
<% end %>

The result I get it this:

<a href="/contr/level1/level2">Contr</a>
<a href="/contr/level1/level2">Level 1</a>
<a href="/contr/level1/level2">Level 2</a>

It makes no sense! Why is there the same link for all the items? The titles are ok, but the links not.

Even if I try to display the links only, with b_links.each do |link| the third link is displayed 3 times. What could be the problem here?

I even tried to make b_links array to contain the strings returned from the url_for method, but without success.


Solution

  • If you are at the deepest level, :controller, :level1 and :level2 are all set.

    If you try to make a path with {:controller => "contr"} it will add that to the current environment. This is very easy, and allows us to write something like {:action => 'edit'} which will use the current controller.

    So you will have to adapt your hash to be something like

     [{:controller=>"contr", :level1 => nil, :level2 => nil}, 
      {:level1=>"level1", :controller=>"contr", :level2 => nil}, 
      {:level1=>"level1", :level2=>"level2", :controller=>"contr"}]
    

    Hope this helps.