Como posso descobrir a rota atual no Rails?

210

Eu preciso conhecer a rota atual em um filtro no Rails. Como posso descobrir o que é?

Estou usando recursos REST e não vejo rotas nomeadas.

luca
fonte
3
O que você está tentando conseguir com isso? Quando você diz "rota", você quer dizer "URI"?
JDL
quaisquer pensamentos sobre como obtê-lo no middleware .
Saurabh

Respostas:

197

Para descobrir o URI:

current_uri = request.env['PATH_INFO']
# If you are browsing http://example.com/my/test/path, 
# then above line will yield current_uri as "/my/test/path"

Para descobrir a rota, ou seja, controlador, ação e parâmetros:

path = ActionController::Routing::Routes.recognize_path "/your/path/here/"

# ...or newer Rails versions:
#
path = Rails.application.routes.recognize_path('/your/path/here')

controller = path[:controller]
action = path[:action]
# You will most certainly know that params are available in 'params' hash
Swanand
fonte
2
Você saberia se essa é a mesma / certa maneira de fazer isso no Rails 3? Tenho certeza de que ainda está acessível, mas só quero ter certeza de que estou cumprindo as últimas convenções.
John
37
O controlador e a ação atuais estão sempre disponíveis em params[:controller]e params[:action]. No entanto, fora dela, se você deseja reconhecer a rota, essa API não está mais disponível. Agora ele mudou ActionDispatch::Routinge eu ainda não testei recognize_path.
quer
36
É melhor usar request.pathpara encontrar o caminho atual.
21412 Daniel Brockman
2
Você também pode ligar request.env['ORIGINAL_FULLPATH']para incluir os possíveis parâmetros no caminho, veja minha resposta abaixo.
DuArme
2
current_uri = request.env ['PATH_INFO'] não funciona se o trailing_slash estiver definido nas rotas
Gediminas
297

Se você estiver tentando processar algo especial em uma exibição, poderá usar current_page?como em:

<% if current_page?(:controller => 'users', :action => 'index') %>

... ou uma ação e id ...

<% if current_page?(:controller => 'users', :action => 'show', :id => 1) %>

... ou uma rota nomeada ...

<% if current_page?(users_path) %>

...e

<% if current_page?(user_path(1)) %>

Como current_page?requer um controlador e uma ação, quando me preocupo apenas com o controlador, faço um current_controller?método no ApplicationController:

  def current_controller?(names)
    names.include?(current_controller)
  end

E use-o assim:

<% if current_controller?('users') %>

... que também funciona com vários nomes de controladores ...

<% if current_controller?(['users', 'comments']) %>
IAmNaN
fonte
27
Observe que você também pode usar a current_page? com rotas nomeadas: current_page? (users_path)
tothemario
Bom para omario. Eu não sabia disso. Estou modificando a resposta.
IAmNaN
ele retorna true qualquer endereço é "/ users", "/ Users /", "/ usuários smth = sdfasf?" .... coisa Às vezes não é tão bom na prática
Gediminas
4
controller_namee action_namesão bons para uso em ajudantes e visualizações para esse tipo de coisa também.
Matt Connolly
1
Em uma vista você também pode simplesmente fazer <% if params [: ação] == 'show' %>, assim você não precisa o controlador
rmcsharry
149

Solução mais simples que eu posso encontrar em 2015 (verificada usando o Rails 4, mas também deve funcionar com o Rails 3)

request.url
# => "http://localhost:3000/lists/7/items"
request.path
# => "/lists/7/items"
weltschmerz
fonte
1
E se você quiser o id na vista: <% = request.path_parameters [: id]%>
rmcsharry
Isso é incrível! Use isso de forma parcial para redirecionar para a página atual com novos parâmetros. <form action="<%= request.path %>">
XHocquet
19

Você consegue fazer isso

Rails.application.routes.recognize_path "/your/path"

Funciona para mim no Rails 3.1.0.rc4

Lucas Renan
fonte
11

No trilhos 3, você pode acessar o objeto Rack :: Mount :: RouteSet através do objeto Rails.application.routes e, em seguida, chamar o reconhecimento diretamente

route, match, params = Rails.application.routes.set.recognize(controller.request)

que obtém a primeira (melhor) correspondência, o seguinte formulário de bloco faz um loop nas rotas correspondentes:

Rails.application.routes.set.recognize(controller.request) do |r, m, p|
  ... do something here ...
end

depois de ter a rota, você pode obter o nome da rota via route.name. Se você precisar obter o nome da rota para uma URL específica, não o caminho da solicitação atual, precisará simular um objeto de solicitação falsa para passar ao rack, confira ActionController :: Routing :: Routes.recognize_path para ver como eles estão fazendo isso.

KinOfCain
fonte
5
Erro:undefined method 'recognize' for #<Journey::Routes:0x007f893dcfa648>
fguillen
7

Com base na sugestão @AmNaN (mais detalhes):

class ApplicationController < ActionController::Base

 def current_controller?(names)
  names.include?(params[:controller]) unless params[:controller].blank? || false
 end

 helper_method :current_controller?

end

Agora você pode chamá-lo, por exemplo, em um layout de navegação para marcar itens da lista como ativos:

<ul class="nav nav-tabs">
  <li role="presentation" class="<%= current_controller?('items') ? 'active' : '' %>">
    <%= link_to user_items_path(current_user) do %>
      <i class="fa fa-cloud-upload"></i>
    <% end %>
  </li>
  <li role="presentation" class="<%= current_controller?('users') ? 'active' : '' %>">
    <%= link_to users_path do %>
      <i class="fa fa-newspaper-o"></i>
    <% end %>
  </li>
  <li role="presentation" class="<%= current_controller?('alerts') ? 'active' : '' %>">
    <%= link_to alerts_path do %>
      <i class="fa fa-bell-o"></i>
    <% end %>
  </li>
</ul>

Para as rotas userse alerts, current_page?seria suficiente:

 current_page?(users_path)
 current_page?(alerts_path)

Mas com rotas aninhadas e solicitação de todas as ações de um controlador (comparável a items), current_controller?foi o melhor método para mim:

 resources :users do 
  resources :items
 end

A primeira entrada do menu é ativada para as seguintes rotas:

   /users/x/items        #index
   /users/x/items/x      #show
   /users/x/items/new    #new
   /users/x/items/x/edit #edit
neonmate
fonte
4

Eu vou assumir que você quer dizer o URI:

class BankController < ActionController::Base
  before_filter :pre_process 

  def index
    # do something
  end

  private
    def pre_process
      logger.debug("The URL" + request.url)
    end
end

Conforme seu comentário abaixo, se você precisar do nome do controlador, basta fazer o seguinte:

  private
    def pre_process
      self.controller_name        #  Will return "order"
      self.controller_class_name  # Will return "OrderController"
    end
Aaron Rustad
fonte
sim eu fiz isso, mas esperava de uma maneira melhor. O que eu preciso é saber qual controlador foi chamado, mas eu tenho recursos aninhados bastante complicados .. request.path_parameters ('controller') não parece funcionar corretamente para mim.
luca
Não há necessidade de self.in self.controller_nameeself.controller_class_name
weltschmerz
4

Você também precisa dos parâmetros :

current_fullpath = request.env ['ORIGINAL_FULLPATH']
# Se você estiver navegando em http://example.com/my/test/path?param_n=N 
# então current_fullpath apontará para "/ my / test / path? param_n = N"

E lembre-se de que você sempre pode ligar <%= debug request.env %>para ver todas as opções disponíveis.

DuArme
fonte
4

request.url

request.path #para obter o caminho, exceto o URL base

Charles Skariah
fonte
2

Você pode ver todas as rotas via rake: routes (isso pode ajudá-lo).

James Schorr
fonte
Prefiro abrir uma nova guia com um caminho inválido e ver todos os caminhos / rotas do navegador, pois são mais bonitos. Mas acho que isso não ajuda na rota atual.
ahnbizcad
0

Você pode fazer request.env['REQUEST_URI']para ver o URI completo solicitado. Ele exibirá algo como abaixo

http://localhost:3000/client/1/users/1?name=test
Vbp
fonte
0

Você consegue fazer isso:

def active_action?(controller)
   'active' if controller.remove('/') == controller_name
end

Agora, você pode usar assim:

<%= link_to users_path, class: "some-class #{active_action? users_path}" %>
Tiago Cassio
fonte