Navigation Bar no Rails

Esses dias eu achei um template pronto na internet (modestamente, sou um péssimo designer) que vinha com uma navbar. Achei bacana e comecei a pensar num jeito Rails de fazer algo bonitinho: ao clicar num item da navbar, esse item fica selecionado.

A primeira coisa que eu pensei, foi em algo como:

minha.url/do/site?current=ATUAL

Tendo, digamos, algo como HomeController, PostController e CommentController, ATUAL podia variar entre Home, Post e Comment. Uma solução, relativamente, clean. Então voltei à Ruby on Rails: Talk e fiz a pergunta: qual a melhor forma de abordar esse problema?

O resultado foi essa discussão: http://groups.google.com/group/rubyonrails-talk/browse_thread/thread/0c0378e25f2d9343

O código que comentei na discussão é o que segue:

app/helpers/home_helper.rb

  1. module HomeHelper
  2.   def build_navbar(items)
  3.     # If I reached the site right now, params[:current]
  4.     # is null.
  5.     params[:current] = "home" if params[:current].nil?
  6.  
  7.     menu=""
  8.  
  9.     items.each do |item|
  10.       menu += content_tag :li, :class => is_current?(item) do
  11.         link_to item, send( "#{item}_url", { :current => item } )
  12.       end
  13.     end
  14.  
  15.     return menu
  16.   end
  17.  
  18.   # Methods ending by ‘?’ returns either "true" or "false"
  19.   # But using it here in "other" context increases
  20.   # readbility.
  21.   def is_current?(item)
  22.     (item == params[:current]) ? "current" : nil
  23.   end
  24. end

#app/views/layouts/post.html.erb

  1. [...]
  2. <div  id="nav">
  3. <ul>
  4. <%= build_navbar %w(home posts articles photos) %>
  5. </ul>
  6. </div>
  7. [...]

É um código bonitinho, até… Mas eu podia ter usado um params[:current] ||= “home”. :-P

Mas esse código não funciona perfeitamente. Se eu entrar no site via minha.url/do/site/posts, por exemplo, params[:current] não está setada e será setada para “home”, apesar de eu não estar em HomeController. :-)

Então eu comecei a pensar: o que eu posso fazer pra deixar esse código melhor e funcionando sempre? Eu tenho MESMO que usar algo feio como “?current=[home|post|whatever]“? O Rails não tem nada que facilite isso também?

Comecei a procurar no Google por isso. Não lembro as keywords, mas deve ter sido algo como “current controller name rails”, eu descobri um tal de controller.controller_name. E funciona muito bem. :-)

O resultado?

  1. module HomeHelper
  2.   # Build an navbar with items from the givem
  3.   # array. Current nav item would get an
  4.   # "current" CSS’ class.
  5.   def build_navbar(items)
  6.     menu=""
  7.  
  8.     items.each do |item|
  9.       menu += content_tag :li, :class => is_current?(item) do
  10.         link_to item, send( "#{item}_url" )
  11.       end
  12.     end
  13.  
  14.     return menu
  15.   end
  16.  
  17.   # Methods ending by ‘?’ returns either "true" or "false"
  18.   # But using it here in "other" context increases
  19.   # readbility.
  20.   def is_current?(item)
  21.     (item == controller.controller_name) ? "current" : nil
  22.   end
  23. end

MUITO melhor. :-)

Leave a Reply