Comment puis-je trouver l'itinéraire actuel dans Rails?


212

J'ai besoin de connaître l'itinéraire actuel dans un filtre dans Rails. Comment puis-je savoir ce que c'est?

Je fais des ressources REST et je ne vois aucune route nommée.


3
Qu'essayez-vous d'accomplir avec cela? Quand vous dites «route», voulez-vous dire «URI»?
jdl

toute réflexion sur la façon de l'obtenir dans le middleware .
Saurabh

Réponses:


197

Pour connaître l'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"

Pour connaître l'itinéraire, c'est-à-dire le contrôleur, l'action et les paramètres:

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
Sauriez-vous savoir si c'est la même / bonne façon de le faire dans Rails 3? Je suis sûr qu'il est toujours accessible, mais je veux juste être sûr que j'adhère aux dernières conventions.
John

37
Le contrôleur et l'action actuels sont toujours disponibles dans params[:controller]et params[:action]. Cependant, en dehors de celui-ci, si vous souhaitez reconnaître l'itinéraire, cette API n'est plus disponible. Il est maintenant passé à ActionDispatch::Routinget je ne l'ai pas encore essayé recognize_path.
Swanand

38
Il vaut mieux l'utiliser request.pathpour trouver le chemin actuel.
Daniel Brockman

2
Vous pouvez également appeler request.env['ORIGINAL_FULLPATH']pour inclure les paramètres possibles dans le chemin d'accès, voir ma réponse ci-dessous.
DuArme

2
current_uri = request.env ['PATH_INFO'] ne fonctionne pas si trailing_slash est défini dans les routes
Gediminas

297

Si vous essayez de cas spécial quelque chose dans une vue, vous pouvez utiliser current_page?comme dans:

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

... ou une action et id ...

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

... ou un itinéraire nommé ...

<% if current_page?(users_path) %>

...et

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

Parce que current_page?nécessite à la fois un contrôleur et une action, lorsque je me soucie uniquement du contrôleur, je crée une current_controller?méthode dans ApplicationController:

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

Et utilisez-le comme ceci:

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

... qui fonctionne également avec plusieurs noms de contrôleurs ...

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

27
Notez que vous pouvez également utiliser current_page? avec des routes nommées: current_page? (users_path)
tothemario

Joli tothemario. Je ne le savais pas. Je modifie la réponse.
IAmNaN

il retourne vrai quelle que soit l'adresse "/ users", "/ users /", "/ users? smth = sdfasf" .... Parfois, ce n'est pas une si bonne chose dans la pratique
Gediminas

4
controller_nameet action_namesont bons pour une utilisation dans les aides et les vues pour ce genre de chose aussi.
Matt Connolly

1
Dans une vue, vous pouvez également faire <% if params [: action] == 'show'%> afin de ne pas avoir besoin du contrôleur
rmcsharry

151

Solution la plus simple que j'ai pu trouver en 2015 (vérifiée avec Rails 4, mais devrait également fonctionner avec Rails 3)

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

1
Et si vous voulez l'ID dans la vue: <% = request.path_parameters [: id]%>
rmcsharry

C'est génial! Utilisez-le sous une forme partielle pour rediriger vers la page actuelle avec de nouveaux paramètres. <form action="<%= request.path %>">
xHocquet

19

Tu peux le faire

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

Cela fonctionne pour moi dans les rails 3.1.0.rc4


11

Dans les rails 3, vous pouvez accéder à l'objet Rack :: Mount :: RouteSet via l'objet Rails.application.routes, puis appeler reconnaître directement dessus

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

qui obtient la première (meilleure) correspondance, la forme de bloc suivante fait une boucle sur les routes correspondantes:

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

une fois que vous avez l'itinéraire, vous pouvez obtenir le nom de l'itinéraire via route.name. Si vous devez obtenir le nom de la route pour une URL particulière, pas le chemin de demande actuel, vous devrez alors simuler un faux objet de demande à transmettre au rack, consultez ActionController :: Routing :: Routes.recognize_path pour voir comment ils le font.


5
Erreur:undefined method 'recognize' for #<Journey::Routes:0x007f893dcfa648>
fguillen

7

Basé sur la suggestion @AmNaN (plus de détails):

class ApplicationController < ActionController::Base

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

 helper_method :current_controller?

end

Vous pouvez maintenant l'appeler, par exemple dans une disposition de navigation pour marquer les éléments de la liste comme actifs:

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

Pour les routes userset alerts, current_page?cela suffirait:

 current_page?(users_path)
 current_page?(alerts_path)

Mais avec des routes imbriquées et une demande pour toutes les actions d'un contrôleur (comparable à items), current_controller?c'était la meilleure méthode pour moi:

 resources :users do 
  resources :items
 end

La première entrée de menu est ainsi activée pour les itinéraires suivants:

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


4

Je suppose que vous voulez dire l'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

Selon votre commentaire ci-dessous, si vous avez besoin du nom du contrôleur, vous pouvez simplement le faire:

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

oui je l'ai fait, mais j'espérais mieux. Ce dont j'ai besoin, c'est de savoir quel contrôleur a été appelé, mais j'ai des ressources imbriquées assez compliquées. Request.path_parameters ('controller') ne semble pas fonctionner correctement pour moi.
luca

Pas besoin de self.dans self.controller_nameetself.controller_class_name
Weltschmerz

4

Si vous avez également besoin des paramètres :

current_fullpath = request.env ['ORIGINAL_FULLPATH']
# Si vous parcourez http://example.com/my/test/path?param_n=N 
# alors current_fullpath pointera vers "/ mon / test / chemin? param_n = N"

Et n'oubliez pas que vous pouvez toujours appeler <%= debug request.env %>dans une vue pour voir toutes les options disponibles.



2

Vous pouvez voir toutes les routes via rake: routes (cela pourrait vous aider).


Je préfère ouvrir un nouvel onglet avec un chemin non valide et voir tous les chemins / itinéraires depuis le navigateur, car ils sont plus jolis de cette façon. Mais je ne pense pas que cela aide à obtenir l'itinéraire actuel.
ahnbizcad

0

Vous pouvez faire request.env['REQUEST_URI']pour voir l'URI complet demandé .. il produira quelque chose comme ci-dessous

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

0

Tu peux le faire:

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

Maintenant, vous pouvez utiliser comme ceci:

<%= link_to users_path, class: "some-class #{active_action? users_path}" %>
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.