Làm thế nào tôi có thể tìm ra tuyến đường hiện tại trong Rails?


210

Tôi cần biết tuyến đường hiện tại trong bộ lọc trong Rails. Làm thế nào tôi có thể tìm ra nó là gì?

Tôi đang làm tài nguyên REST và không thấy tuyến đường nào được đặt tên.


3
Bạn đang cố gắng thực hiện điều gì với điều này? Khi bạn nói "tuyến đường", bạn có nghĩa là "URI"?
jdl

bất kỳ suy nghĩ về làm thế nào để có được nó trong phần mềm trung gian .
Saurabh

Câu trả lời:


197

Để tìm hiểu 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"

Để tìm ra tuyến đường tức là bộ điều khiển, hành động và thông số:

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
Bạn có tình cờ biết liệu đây có phải là cách tương tự / đúng để làm điều đó trong Rails 3 không? Tôi chắc chắn rằng nó vẫn có thể truy cập được, nhưng tôi chỉ muốn chắc chắn rằng tôi đang tuân thủ các quy ước mới nhất.
Giăng

37
Bộ điều khiển và hành động hiện tại luôn có sẵn trong params[:controller]params[:action]. Tuy nhiên, bên ngoài nó, nếu bạn muốn nhận ra tuyến đường, API này không còn khả dụng nữa. Bây giờ nó đã được chuyển sang ActionDispatch::Routingvà tôi chưa thử recognize_pathnó.
Swanand

36
Tốt hơn là sử dụng request.pathđể tìm đường dẫn hiện tại.
Daniel Brockman

2
Bạn cũng có thể gọi request.env['ORIGINAL_FULLPATH']để bao gồm các tham số có thể trong đường dẫn, xem câu trả lời của tôi dưới đây.
DuArme

2
current_uri = request.env ['PATH_INFO'] không hoạt động nếu trailing_slash được đặt trong các tuyến đường
Gediminas

297

Nếu bạn đang cố gắng đặc biệt một cái gì đó trong một khung nhìn, bạn có thể sử dụng current_page?như trong:

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

... hoặc một hành động và id ...

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

... hoặc một tuyến đường được đặt tên ...

<% if current_page?(users_path) %>

... và

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

Bởi vì current_page?yêu cầu cả bộ điều khiển và hành động, khi tôi chỉ quan tâm đến bộ điều khiển, tôi tạo một current_controller?phương thức trong ApplicationContoder:

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

Và sử dụng nó như thế này:

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

... cũng hoạt động với nhiều tên bộ điều khiển ...

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

27
Lưu ý rằng bạn cũng có thể sử dụng current_page? với các tuyến được đặt tên: current_page? (users_path)
tothemario

Đẹp tothemario. Tôi không biết điều đó. Tôi đang sửa đổi câu trả lời.
IAmNaN

nó trả về đúng bất cứ địa chỉ nào là "/ users", "/ users /", "/ users? smth = sdfasf" .... Đôi khi không thực sự tốt trong thực tế
Gediminas

4
controller_nameaction_namecũng tốt để sử dụng trong trợ giúp và quan điểm cho loại điều này quá.
Matt Connolly

1
Trong chế độ xem, bạn cũng chỉ có thể thực hiện <% if params [: action] == 'show'%> vì vậy bạn không cần bộ điều khiển
rmcsharry

149

Giải pháp đơn giản nhất tôi có thể đưa ra vào năm 2015 (được xác minh bằng Rails 4, nhưng cũng nên hoạt động bằng Rails 3)

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

1
Và nếu bạn muốn id trong chế độ xem: <% = request.path_parameter [: id]%>
rmcsharry

Điều này thật tuyệt! Sử dụng điều này trong một hình thức một phần để chuyển hướng đến trang hiện tại với thông số mới. <form action="<%= request.path %>">
xHocquet

19

Bạn có thể làm được việc này

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

Nó hoạt động với tôi trong rails 3.1.0.rc4


11

Trong rails 3, bạn có thể truy cập đối tượng Rack :: Mount :: Routeset thông qua đối tượng Rails.application.routes, sau đó gọi nhận dạng trực tiếp trên nó

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

có kết quả khớp đầu tiên (tốt nhất), các vòng lặp dạng khối sau trên các tuyến khớp:

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

một khi bạn có tuyến đường, bạn có thể lấy tên tuyến đường qua route.name. Nếu bạn cần lấy tên tuyến đường cho một URL cụ thể, không phải đường dẫn yêu cầu hiện tại, thì bạn sẽ cần phải giả lập một đối tượng yêu cầu giả mạo để chuyển xuống rack, hãy xem ActionContoder :: Routing :: Routes.recognize_path để xem họ đang làm điều đó như thế nào


5
Lỗi:undefined method 'recognize' for #<Journey::Routes:0x007f893dcfa648>
fguillen

7

Dựa trên đề xuất @AmNaN (biết thêm chi tiết):

class ApplicationController < ActionController::Base

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

 helper_method :current_controller?

end

Bây giờ bạn có thể gọi nó, ví dụ như trong bố trí điều hướng để đánh dấu các mục danh sách là hoạt động:

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

Cho usersalertstuyến đường, current_page?sẽ là đủ:

 current_page?(users_path)
 current_page?(alerts_path)

Nhưng với các tuyến đường lồng nhau và yêu cầu tất cả các hành động của bộ điều khiển (có thể so sánh với items), current_controller?là phương pháp tốt hơn đối với tôi:

 resources :users do 
  resources :items
 end

Mục menu đầu tiên là cách hoạt động cho các tuyến sau:

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


4

Tôi sẽ giả sử bạn có nghĩa 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

Theo nhận xét của bạn dưới đây, nếu bạn cần tên của bộ điều khiển, bạn chỉ cần làm điều này:

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

vâng tôi đã làm điều đó, nhưng tôi hy vọng theo cách tốt hơn. Điều tôi cần là biết bộ điều khiển nào đã được gọi, nhưng tôi có các tài nguyên lồng nhau khá phức tạp .. request.path_parameter ('bộ điều khiển') dường như không hoạt động đúng với tôi.
luca

Không cần self.trong self.controller_nameself.controller_class_name
Weltschmerz 24/07/2015

4

Nếu bạn cũng cần các tham số :

current_fullpath = request.env ['ORIGINAL_FULLPATH']
# Nếu bạn đang duyệt http://example.com/my/test/path?param_n=N 
# thì current_fullpath sẽ trỏ đến "/ my / test / path? param_n = N"

Và hãy nhớ rằng bạn luôn có thể gọi <%= debug request.env %>trong một khung nhìn để xem tất cả các tùy chọn có sẵn.


4

request.url

request.path # để có được đường dẫn ngoại trừ url cơ sở


2

Bạn có thể xem tất cả các tuyến thông qua rake: tuyến (điều này có thể giúp bạn).


Tôi thích mở một tab mới có đường dẫn không hợp lệ và xem tất cả các đường dẫn / tuyến đường từ trình duyệt, vì chúng đẹp hơn theo cách đó. Nhưng tôi không nghĩ rằng điều này sẽ giúp có được lộ trình hiện tại.
ahnbizcad

0

Bạn có thể làm request.env['REQUEST_URI']để xem URI được yêu cầu đầy đủ .. nó sẽ xuất ra một cái gì đó như dưới đây

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

0

Bạn có thể làm được việc này:

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

Bây giờ, bạn có thể sử dụng như thế này:

<%= link_to users_path, class: "some-class #{active_action? users_path}" %>
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.