¿Cómo puedo encontrar la ruta actual en Rails?


212

Necesito saber la ruta actual en un filtro en Rails. ¿Cómo puedo saber de qué se trata?

Estoy haciendo recursos REST y no veo rutas con nombre.


3
¿Qué estás tratando de lograr con esto? Cuando dices "ruta", ¿te refieres a "URI"?
jdl

alguna idea sobre cómo obtenerlo en middleware .
Saurabh

Respuestas:


197

Para descubrir el 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 averiguar la ruta, es decir, controlador, acción y 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

2
¿Sabrías si esta es la misma / correcta forma de hacerlo en Rails 3? Estoy seguro de que todavía es accesible, pero solo quiero estar seguro de que me adhiero a las últimas convenciones.
John

37
El controlador actual y la acción siempre están disponibles en params[:controller]y params[:action]. Sin embargo, fuera de él, si desea reconocer la ruta, esta API ya no está disponible. Ahora ha cambiado ActionDispatch::Routingy todavía no lo he probado recognize_path.
Swanand

38
Es mejor usarlo request.pathpara encontrar la ruta actual.
Daniel Brockman

2
También puede llamar request.env['ORIGINAL_FULLPATH']para incluir los posibles parámetros en la ruta, vea mi respuesta a continuación.
DuArme

2
current_uri = request.env ['PATH_INFO'] no funciona si trailing_slash está configurado en rutas
Gediminas

297

Si está intentando poner algo especial en una vista, puede usarlo current_page?como en:

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

... o una acción e id ...

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

... o una ruta con nombre ...

<% if current_page?(users_path) %>

...y

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

Debido a que current_page?requiere un controlador y una acción, cuando me preocupo solo por el controlador, hago un current_controller?método en ApplicationController:

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

Y úsalo así:

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

... que también funciona con múltiples nombres de controlador ...

<% if current_controller?(['users', 'comments']) %>

27
Tenga en cuenta que también puede usar current_page? con rutas con nombre: CURRENT_PAGE (users_path)?
tothemario

Buen tothemario. No lo sabia. Estoy modificando la respuesta.
IAmNaN

devuelve verdadero sea cual sea la dirección "/ users", "/ users /", "/ users? smth = sdfasf" .... A veces no es algo tan bueno en la práctica
Gediminas

44
controller_namey action_nameson buenos para usar en ayudantes y vistas para este tipo de cosas también.
Matt Connolly

1
En una vista, también puede hacer <% if params [: action] == 'show'%> para que no necesite el controlador
rmcsharry

151

La solución más simple que puedo encontrar en 2015 (verificado con Rails 4, pero también debería funcionar con Rails 3)

request.url
# => "http://localhost:3000/lists/7/items"
request.path
# => "/lists/7/items"

1
Y si desea la identificación en la vista: <% = request.path_parameters [: id]%>
rmcsharry

¡Esto es asombroso! Use esto de forma parcial para redirigir a la página actual con nuevos parámetros. <form action="<%= request.path %>">
xHocquet el

19

Puedes hacerlo

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

A mí me funciona en rails 3.1.0.rc4


11

En rails 3 puede acceder al objeto Rack :: Mount :: RouteSet a través del objeto Rails.application.routes, luego llame a reconocer en él directamente

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

que obtiene la primera (mejor) coincidencia, la siguiente forma de bloque recorre las rutas coincidentes:

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

una vez que tenga la ruta, puede obtener el nombre de la ruta a través de route.name. Si necesita obtener el nombre de la ruta para una URL en particular, no la ruta de solicitud actual, deberá simular un objeto de solicitud falso para pasar al bastidor, consulte ActionController :: Routing :: Routes.recognize_path para ver cómo lo están haciendo.


55
Error:undefined method 'recognize' for #<Journey::Routes:0x007f893dcfa648>
fguillen

7

Basado en la sugerencia de @AmNaN (más detalles):

class ApplicationController < ActionController::Base

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

 helper_method :current_controller?

end

Ahora puede llamarlo, por ejemplo, en un diseño de navegación para marcar elementos de la lista como activos:

<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 las rutas usersy alerts, current_page?sería suficiente:

 current_page?(users_path)
 current_page?(alerts_path)

Pero con rutas anidadas y solicitud de todas las acciones de un controlador (comparable con items), current_controller?fue el mejor método para mí:

 resources :users do 
  resources :items
 end

La primera entrada del menú está activa de esa manera para las siguientes rutas:

   /users/x/items        #index
   /users/x/items/x      #show
   /users/x/items/new    #new
   /users/x/items/x/edit #edit


4

Asumiré que te refieres al 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

Según su comentario a continuación, si necesita el nombre del controlador, simplemente puede hacer esto:

  private
    def pre_process
      self.controller_name        #  Will return "order"
      self.controller_class_name  # Will return "OrderController"
    end

Sí, lo hice, pero esperaba que fuera mejor. Lo que necesito es saber a qué controlador se ha llamado, pero tengo recursos anidados bastante complicados ... request.path_parameters ('controlador') no parece funcionar correctamente para mí.
luca

No hay necesidad de que self.en self.controller_nameeself.controller_class_name
weltschmerz

4

Si también necesita los parámetros :

current_fullpath = request.env ['ORIGINAL_FULLPATH']
# Si está navegando http://example.com/my/test/path?param_n=N 
# entonces current_fullpath apuntará a "/ my / test / path? param_n = N"

Y recuerde que siempre puede llamar <%= debug request.env %>desde una vista para ver todas las opciones disponibles.



2

Puede ver todas las rutas a través de rake: rutas (esto podría ayudarlo).


Prefiero abrir una nueva pestaña con una ruta no válida y ver todas las rutas / rutas desde el navegador, ya que son más bonitas de esa manera. Pero no creo que esto ayude a obtener la ruta actual.
ahnbizcad

0

Puede hacer request.env['REQUEST_URI']para ver el URI completo solicitado ... generará algo como lo siguiente

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

0

Puedes hacerlo:

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

Ahora, puedes usar así:

<%= link_to users_path, class: "some-class #{active_action? users_path}" %>
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.