Wie kann ich die aktuelle Route in Rails herausfinden?

210

Ich muss die aktuelle Route in einem Filter in Rails kennen. Wie kann ich herausfinden, was es ist?

Ich mache REST-Ressourcen und sehe keine benannten Routen.

luca
quelle
3
Was versuchst du damit zu erreichen? Wenn Sie "Route" sagen, meinen Sie "URI"?
JDL
irgendwelche Gedanken darüber, wie man es in Middleware bekommt .
Saurabh

Antworten:

197

So finden Sie die URI heraus:

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"

So ermitteln Sie die Route, dh Controller, Aktion und Parameter:

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
quelle
2
Würdest du zufällig wissen, ob dies der gleiche / richtige Weg ist, dies in Rails 3 zu tun? Ich bin mir sicher, dass es immer noch zugänglich ist, aber ich möchte nur sichergehen, dass ich mich an die neuesten Konventionen halte.
John
37
Der aktuelle Controller und die Aktion sind immer in params[:controller]und verfügbar params[:action]. Außerhalb davon ist diese API nicht mehr verfügbar, wenn Sie die Route erkennen möchten. Es hat sich jetzt verschoben ActionDispatch::Routingund ich habe recognize_pathes noch nicht ausprobiert .
Swanand
36
Es ist besser request.path, den aktuellen Pfad zu finden.
Daniel Brockman
2
Sie können auch aufrufen request.env['ORIGINAL_FULLPATH'], um die möglichen Parameter in den Pfad aufzunehmen, siehe meine Antwort unten.
DuArme
2
current_uri = request.env ['PATH_INFO'] funktioniert nicht, wenn trailing_slash in Routen gesetzt ist
Gediminas
297

Wenn Sie versuchen, einen Sonderfall in einer Ansicht zu erstellen, können Sie Folgendes verwenden current_page?:

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

... oder eine Aktion und ID ...

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

... oder eine benannte Route ...

<% if current_page?(users_path) %>

...und

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

Da current_page?sowohl ein Controller als auch eine Aktion erforderlich sind, erstelle ich current_controller?in ApplicationController eine Methode , wenn ich mich nur um den Controller kümmere :

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

Und benutze es so:

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

... was auch mit mehreren Controllernamen funktioniert ...

<% if current_controller?(['users', 'comments']) %>
IAmNaN
quelle
27
Beachten Sie, dass Sie auch current_page verwenden können? mit benannten Routen: current_page? (users_path)
tothemario
Nettes Szenario. Das wusste ich nicht. Ich ändere die Antwort.
IAmNaN
es gibt true zurück, egal welche Adresse "/ users", "/ users /", "/ users? smth = sdfasf" ist .... Manchmal in der Praxis nicht so gut
Gediminas
4
controller_nameund action_nameeignen sich auch für Helfer und Ansichten für solche Dinge.
Matt Connolly
1
In einer Ansicht können Sie auch nur <% if params [: action] == 'show'%>
ausführen,
149

Die einfachste Lösung, die ich 2015 finden kann (überprüft mit Rails 4, sollte aber auch mit Rails 3 funktionieren)

request.url
# => "http://localhost:3000/lists/7/items"
request.path
# => "/lists/7/items"
weltschmerz
quelle
1
Und wenn Sie die ID in der Ansicht haben möchten: <% = request.path_parameters [: id]%>
rmcsharry
Das ist fantastisch! Verwenden Sie dies in Teilform, um mit neuen Parametern zur aktuellen Seite umzuleiten. <form action="<%= request.path %>">
xHocquet
19

Du kannst das

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

Es funktioniert bei mir in Rails 3.1.0.rc4

Lucas Renan
quelle
11

In Rails 3 können Sie über das Objekt Rails.application.routes auf das Objekt Rack :: Mount :: RouteSet zugreifen und dann die Erkennung direkt aufrufen

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

Damit wird die erste (beste) Übereinstimmung erzielt. Die folgende Blockform durchläuft die übereinstimmenden Routen:

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

Sobald Sie die Route haben, können Sie den Routennamen über route.name abrufen. Wenn Sie den Routennamen für eine bestimmte URL und nicht den aktuellen Anforderungspfad abrufen müssen, müssen Sie ein gefälschtes Anforderungsobjekt verspotten, um es an das Rack weiterzuleiten. Weitere Informationen finden Sie unter ActionController :: Routing :: Routes.recognize_path wie sie es machen.

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

Basierend auf dem @ AmNaN-Vorschlag (weitere Details):

class ApplicationController < ActionController::Base

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

 helper_method :current_controller?

end

Jetzt können Sie es zB in einem Navigationslayout aufrufen, um Listenelemente als aktiv zu markieren:

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

Für die usersund alertsRouten current_page?würde reichen:

 current_page?(users_path)
 current_page?(alerts_path)

Aber mit verschachtelten Routen und der Anforderung aller Aktionen eines Controllers (vergleichbar mit items) current_controller?war die bessere Methode für mich:

 resources :users do 
  resources :items
 end

Der erste Menüeintrag ist auf diese Weise für folgende Routen aktiv:

   /users/x/items        #index
   /users/x/items/x      #show
   /users/x/items/new    #new
   /users/x/items/x/edit #edit
Neonmate
quelle
4

Ich gehe davon aus, dass Sie die URI meinen:

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

Wenn Sie den Namen des Controllers benötigen, können Sie gemäß Ihrem Kommentar unten einfach Folgendes tun:

  private
    def pre_process
      self.controller_name        #  Will return "order"
      self.controller_class_name  # Will return "OrderController"
    end
Aaron Rustad
quelle
Ja, das habe ich getan, aber ich habe es besser gehofft. Ich muss wissen, welcher Controller aufgerufen wurde, aber ich habe ziemlich komplizierte verschachtelte Ressourcen. Request.path_parameters ('controller') scheint für mich nicht richtig zu funktionieren.
Luca
Keine Notwendigkeit für self.in self.controller_nameundself.controller_class_name
weltschmerz
4

Sollten Sie auch die Parameter benötigen :

current_fullpath = request.env ['ORIGINAL_FULLPATH']
# Wenn Sie http://example.com/my/test/path?param_n=N durchsuchen 
# dann zeigt current_fullpath auf "/ my / test / path? param_n = N"

Und denken Sie daran, dass Sie jederzeit <%= debug request.env %>eine Ansicht aufrufen können , um alle verfügbaren Optionen anzuzeigen.

DuArme
quelle
4

request.url

request.path # um den Pfad mit Ausnahme der Basis-URL abzurufen

Charles Skariah
quelle
2

Sie können alle Routen über Rake: Routen anzeigen (dies kann Ihnen helfen).

James Schorr
quelle
Ich bevorzuge es, eine neue Registerkarte mit einem ungültigen Pfad zu öffnen und alle Pfade / Routen im Browser anzuzeigen, da sie auf diese Weise hübscher sind. Aber ich denke nicht, dass dies hilft, die aktuelle Route zu erhalten.
Ahnbizcad
0

Sie können request.env['REQUEST_URI']den vollständig angeforderten URI anzeigen. Er gibt etwa die folgende Ausgabe aus

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

Du kannst das:

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

Jetzt können Sie Folgendes verwenden:

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