¿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.

luca
fuente
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
Swanand
fuente
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']) %>
IAmNaN
fuente
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"
Weltschmerz
fuente
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

Lucas Renan
fuente
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.

KinOfCain
fuente
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
neonmate
fuente
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
Aaron Rustad
fuente
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.

DuArme
fuente
4

request.url

request.path # para obtener la ruta excepto la url base

Charles Skariah
fuente
2

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

James Schorr
fuente
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
Vbp
fuente
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}" %>
Tiago Cassio
fuente