ChatGPT解决这个技术问题 Extra ChatGPT

How can I find out the current route in Rails?

I need to know the current route in a filter in Rails. How can I find out what it is?

I'm doing REST resources, and see no named routes.

What are you trying to accomplish with this? When you say "route" do you mean "URI"?
any thoughts on how to get it in middleware.

I
IAmNaN

If you are trying to special case something in a view, you can use current_page? as in:

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

...or an action and id...

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

...or a named route...

<% if current_page?(users_path) %>

...and

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

Because current_page? requires both a controller and action, when I care about just the controller I make a current_controller? method in ApplicationController:

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

And use it like this:

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

...which also works with multiple controller names...

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

Note that you can also use current_page? with named routes: current_page?(users_path)
Nice tothemario. I didn't know that. I'm modifying the answer.
controller_name and action_name are good for use in helpers and views for this sort of thing too.
In a view you can also just do <% if params[:action] == 'show' %> so you don't need the controller
In Rails 6 (and probably as early as Rails 4 or 5), you can simply provide an active record object: current_page?(@user) or collection current_page?(@users). Rails uses polymorphic_path under the hood to generate the path from the given active record object. Pretty neat!
S
Swanand

To find out 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"

To find out the route i.e. controller, action and params:

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

Would you happen to know if this is the same/right way to do it in Rails 3? I'm sure it's still accessible, but I just want to be sure that I'm adhering to the latest conventions.
The current controller and action are always available in params[:controller] and params[:action]. However, outside of it, if you want to recognize the route, this API is not available anymore. It has now shifted to ActionDispatch::Routing and I haven't tried out the recognize_path on it yet.
It’s better to use request.path for finding the current path.
You could also call request.env['ORIGINAL_FULLPATH'] to include the possible parameters in the path, see my answer below.
current_uri = request.env['PATH_INFO'] doesn't work if trailing_slash is set in routes
w
weltschmerz

Simplest solution I can come up with in 2015 (verified using Rails 4, but should also work using Rails 3)

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

And if you want the id in the view: <%= request.path_parameters[:id] %>
This is awesome! Use this in a partial form to redirect to the current page with new params. <form action="<%= request.path %>">
L
Lucas Renan

You can do this

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

It works for me in rails 3.1.0.rc4


This returns a hash which is the params hash. Any way to actually get the route object? With the name and then other attributes?
K
KinOfCain

In rails 3 you can access the Rack::Mount::RouteSet object via the Rails.application.routes object, then call recognize on it directly

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

that gets the first (best) match, the following block form loops over the matching routes:

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

once you have the route, you can get the route name via route.name. If you need to get the route name for a particular URL, not the current request path, then you'll need to mock up a fake request object to pass down to rack, check out ActionController::Routing::Routes.recognize_path to see how they're doing it.


Error: undefined method 'recognize' for #<Journey::Routes:0x007f893dcfa648>
A
Alex Kitchens

Based on @AmNaN suggestion (more details):

class ApplicationController < ActionController::Base

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

 helper_method :current_controller?

end

Now you can call it e.g. in a navigation layout for marking list items as active:

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

For the users and alerts routes, current_page? would be enough:

 current_page?(users_path)
 current_page?(alerts_path)

But with nested routes and request for all actions of a controller (comparable with items), current_controller? was the better method for me:

 resources :users do 
  resources :items
 end

The first menu entry is that way active for the following routes:

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

D
Darme

Should you also need the parameters:

current_fullpath = request.env['ORIGINAL_FULLPATH']
# If you are browsing http://example.com/my/test/path?param_n=N 
# then current_fullpath will point to "/my/test/path?param_n=N"

And remember you can always call <%= debug request.env %> in a view to see all the available options.


d
dipole_moment

Or, more elegantly: request.path_info

Source:
Request Rack Documentation


A
Aaron Rustad

I'll assume you mean the 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

As per your comment below, if you need the name of the controller, you can simply do this:

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

yes I did that, but I hoped in a better way. What I need is to know which controller has been called, but I have pretty complicated nested resources.. request.path_parameters('controller') doesn't seem to work properly to me.
No need for self. in self.controller_name and self.controller_class_name
C
Charles Skariah

request.url

request.path #to get path except the base url


J
James Schorr

You can see all routes via rake:routes (this might help you).


I prefer to open a new tab with an invalid path, and see all the path/routes from the browser, since they're prettier that way. But I don't think this helps get the current route.
T
Tiago Cassio

You can do this:

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

Now, you can use like this:

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

D
Dan Rice

I find that the the approved answer, request.env['PATH_INFO'], works for getting the base URL, but this does not always contain the full path if you have nested routes. You can use request.env['HTTP_REFERER'] to get the full path and then see if it matches a given route:

request.env['HTTP_REFERER'].match?(my_cool_path)

V
Vbp

You can do request.env['REQUEST_URI'] to see the full requested URI.. it will output something like below

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