Come posso scoprire il percorso corrente in Rails?


212

Devo conoscere il percorso corrente in un filtro in Rails. Come posso scoprire di cosa si tratta?

Sto facendo risorse REST e non vedo percorsi nominati.


3
Cosa stai cercando di ottenere con questo? Quando dici "route" intendi "URI"?
jdl

qualsiasi pensiero su come ottenerlo nel middleware .
Saurabh,

Risposte:


197

Per scoprire 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"

Per scoprire il percorso, ad esempio controller, azione e parametri:

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
Ti capita di sapere se questo è lo stesso / giusto modo per farlo in Rails 3? Sono sicuro che sia ancora accessibile, ma voglio solo essere sicuro di aderire alle ultime convenzioni.
Giovanni,

37
L'attuale controller e l'azione sono sempre disponibili in params[:controller]e params[:action]. Tuttavia, al di fuori di esso, se si desidera riconoscere il percorso, questa API non è più disponibile. Ora è cambiato ActionDispatch::Routinge non l'ho ancora provato recognize_path.
Swanand,

38
È meglio usare request.pathper trovare il percorso corrente.
Daniel Brockman,

2
Puoi anche chiamare request.env['ORIGINAL_FULLPATH']per includere i possibili parametri nel percorso, vedi la mia risposta di seguito.
DuArme,

2
current_uri = request.env ['PATH_INFO'] non funziona se trailing_slash è impostato nelle rotte
Gediminas,

297

Se stai provando qualcosa di speciale in una vista, puoi usare current_page?come in:

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

... o un'azione e un id ...

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

... o una rotta denominata ...

<% if current_page?(users_path) %>

...e

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

Perché current_page?richiede sia un controller che un'azione, quando mi preoccupo solo del controller faccio un current_controller?metodo in ApplicationController:

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

E usalo in questo modo:

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

... che funziona anche con più nomi di controller ...

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

27
Nota che puoi anche usare current_page? con percorsi denominati: current_page? (users_path)
tothemario

Bel tothemario. Non lo sapevo. Sto modificando la risposta.
IAmNaN,

restituisce vero qualunque sia l'indirizzo "/ Users", "/ Users /", "/ Users? smth = sdfasf" .... A volte non è una cosa così buona in pratica
Gediminas

4
controller_namee action_namesono utili anche per gli helper e le visualizzazioni per questo genere di cose.
Matt Connolly,

1
In una vista puoi anche fare <% if params [: action] == 'show'%> quindi non hai bisogno del controller
rmcsharry,

151

La soluzione più semplice che posso trovare nel 2015 (verificata con Rails 4, ma dovrebbe funzionare anche con Rails 3)

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

1
E se vuoi l'ID nella vista: <% = request.path_parameters [: id]%>
rmcsharry

Questo e spettacolare! Usalo in forma parziale per reindirizzare alla pagina corrente con nuovi parametri. <form action="<%= request.path %>">
xHocquet,

19

Puoi farlo

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

Funziona per me in rails 3.1.0.rc4


11

In rails 3 è possibile accedere all'oggetto Rack :: Mount :: RouteSet tramite l'oggetto Rails.application.routes, quindi chiamare direttamente riconoscere su di esso

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

che ottiene la prima (migliore) corrispondenza, la seguente forma di blocco scorre lungo le rotte corrispondenti:

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

una volta che hai il percorso, puoi ottenere il nome del percorso tramite route.name. Se è necessario ottenere il nome della route per un particolare URL, non il percorso della richiesta corrente, è necessario simulare un oggetto di richiesta falsa da passare al rack, controllare ActionController :: Routing :: Routes.recognize_path per vedere come lo stanno facendo.


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

7

Sulla base del suggerimento @AmNaN (maggiori dettagli):

class ApplicationController < ActionController::Base

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

 helper_method :current_controller?

end

Ora puoi chiamarlo ad es. In un layout di navigazione per contrassegnare gli elementi dell'elenco come attivi:

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

Per i percorsi userse alerts, current_page?sarebbe sufficiente:

 current_page?(users_path)
 current_page?(alerts_path)

Ma con percorsi nidificati e richiesta di tutte le azioni di un controller (paragonabile a items), current_controller?era il metodo migliore per me:

 resources :users do 
  resources :items
 end

La prima voce del menu è attiva in questo modo per i seguenti percorsi:

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


4

Suppongo che intendi 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

Secondo il tuo commento qui sotto, se hai bisogno del nome del controller, puoi semplicemente farlo:

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

si l'ho fatto, ma speravo in un modo migliore. Ciò di cui ho bisogno è sapere quale controller è stato chiamato, ma ho risorse nidificate piuttosto complicate. Request.path_parameters ('controller') non sembra funzionare correttamente con me.
luca,

Non c'è bisogno di self.in self.controller_nameeself.controller_class_name
weltschmerz

4

Dovresti anche avere bisogno dei parametri :

current_fullpath = request.env ['ORIGINAL_FULLPATH']
# Se stai visitando http://example.com/my/test/path?param_n=N 
# quindi current_fullpath punterà a "/ my / test / path? param_n = N"

E ricorda che puoi sempre chiamare <%= debug request.env %>in una vista per vedere tutte le opzioni disponibili.



2

Puoi vedere tutti i percorsi tramite rake: route (questo potrebbe aiutarti).


Preferisco aprire una nuova scheda con un percorso non valido e vedere tutti i percorsi / percorsi dal browser, poiché sono più carini in quel modo. Ma non penso che questo aiuti a ottenere il percorso attuale.
ahnbizcad,

0

Puoi fare request.env['REQUEST_URI']per vedere l'URI completo richiesto .. produrrà qualcosa come sotto

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

0

Puoi farlo:

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

Ora puoi usare così:

<%= link_to users_path, class: "some-class #{active_action? users_path}" %>
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.