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.

luca
la source
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
Swanand
la source
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']) %>
IAmNaN
la source
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"
weltschmerz
la source
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

Lucas Renan
la source
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.

KinOfCain
la source
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
nouveau-né
la source
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
Aaron Rustad
la source
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.

DuArme
la source
4

request.url

request.path #pour obtenir le chemin sauf l'URL de base

Charles Skariah
la source
2

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

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