Bagaimana saya bisa mengetahui rute saat ini di Rails?

212

Saya perlu tahu rute saat ini dalam filter di Rails. Bagaimana saya bisa mengetahui apa itu?

Saya sedang melakukan sumber daya REST, dan tidak melihat rute bernama.

luca
sumber
3
Apa yang ingin Anda capai dengan ini? Ketika Anda mengatakan "rute", maksud Anda "URI"?
jdl
ada pemikiran tentang cara mendapatkannya di middleware .
Saurabh

Jawaban:

197

Untuk mengetahui 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"

Untuk mengetahui rute yaitu pengontrol, aksi dan 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
Swanand
sumber
2
Apakah Anda tahu kalau ini cara yang sama / benar untuk melakukannya di Rails 3? Saya yakin itu masih dapat diakses, tetapi saya hanya ingin memastikan bahwa saya mengikuti konvensi terbaru.
John
37
Kontroler dan tindakan saat ini selalu tersedia di params[:controller]dan params[:action]. Namun, di luar itu, jika Anda ingin mengenali rute, API ini tidak tersedia lagi. Sekarang telah bergeser ke ActionDispatch::Routingdan saya belum mencobanya recognize_path.
Swanand
38
Lebih baik digunakan request.pathuntuk menemukan jalur saat ini.
Daniel Brockman
2
Anda juga dapat menelepon request.env['ORIGINAL_FULLPATH']untuk memasukkan parameter yang mungkin di jalur, lihat jawaban saya di bawah ini.
DuArme
2
current_uri = request.env ['PATH_INFO'] tidak berfungsi jika trailing_slash disetel dalam rute
Gediminas
297

Jika Anda mencoba membuat kasus khusus sesuatu dalam tampilan, Anda dapat menggunakan current_page?seperti pada:

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

... atau tindakan dan id ...

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

... atau rute bernama ...

<% if current_page?(users_path) %>

...dan

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

Karena current_page?membutuhkan pengontrol dan aksi, saat saya peduli hanya pengontrolnya, saya membuat current_controller?metode di ApplicationController:

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

Dan gunakan seperti ini:

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

... yang juga berfungsi dengan beberapa nama pengontrol ...

<% if current_controller?(['users', 'comments']) %>
IAmNaN
sumber
27
Perhatikan bahwa Anda juga dapat menggunakan current_page? dengan rute bernama: current_page? (users_path)
tothemario
Tothemario yang bagus. Saya tidak tahu itu. Saya mengubah jawabannya.
IAmNaN
ia mengembalikan benar alamat apa pun yang "/ pengguna", "/ pengguna /", "/ pengguna bertiga = sdfasf?" .... hal Kadang-kadang tidak begitu baik dalam praktek
Gediminas
4
controller_namedan action_namebaik untuk digunakan dalam pembantu dan pandangan untuk hal semacam ini juga.
Matt Connolly
1
Dalam tampilan Anda juga bisa melakukan <% jika params [: action] == 'show'%> sehingga Anda tidak memerlukan controller
rmcsharry
151

Solusi paling sederhana yang dapat saya buat pada tahun 2015 (diverifikasi menggunakan Rails 4, tetapi juga harus bekerja menggunakan Rails 3)

request.url
# => "http://localhost:3000/lists/7/items"
request.path
# => "/lists/7/items"
weltschmerz
sumber
1
Dan jika Anda ingin id dalam tampilan: <% = request.path_parameters [: id]%>
rmcsharry
Ini luar biasa! Gunakan ini dalam bentuk parsial untuk mengarahkan ulang ke halaman saat ini dengan params baru. <form action="<%= request.path %>">
xHocquet
19

Kamu bisa melakukan ini

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

Ini bekerja untuk saya di rel 3.1.0.rc4

Lucas Renan
sumber
11

Di rel 3 Anda dapat mengakses objek Rack :: Mount :: RouteSet melalui objek Rails.application.routes, lalu panggil kenali di atasnya secara langsung

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

yang mendapatkan kecocokan pertama (terbaik), bentuk blok berikut ini melingkupi rute yang cocok:

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

setelah Anda memiliki rute, Anda bisa mendapatkan nama rute melalui route.name. Jika Anda perlu mendapatkan nama rute untuk URL tertentu, bukan jalur permintaan saat ini, maka Anda harus membuat tiruan objek permintaan palsu untuk diturunkan ke rak, periksa ActionController :: Routing :: Routes :: Routes. Routogn.recognize_path untuk melihat bagaimana mereka melakukannya.

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

Berdasarkan saran @AmNaN (lebih detail):

class ApplicationController < ActionController::Base

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

 helper_method :current_controller?

end

Sekarang Anda dapat menyebutnya mis dalam tata letak navigasi untuk menandai item daftar sebagai aktif:

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

Untuk usersdan alertsrute, current_page?akan cukup:

 current_page?(users_path)
 current_page?(alerts_path)

Tetapi dengan rute bersarang dan permintaan untuk semua tindakan pengontrol (sebanding dengan items), current_controller?adalah metode yang lebih baik untuk saya:

 resources :users do 
  resources :items
 end

Entri menu pertama aktif untuk rute-rute berikut:

   /users/x/items        #index
   /users/x/items/x      #show
   /users/x/items/new    #new
   /users/x/items/x/edit #edit
neonatus
sumber
4

Saya akan menganggap Anda maksud 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

Sesuai komentar Anda di bawah ini, jika Anda membutuhkan nama controller, Anda dapat melakukan ini:

  private
    def pre_process
      self.controller_name        #  Will return "order"
      self.controller_class_name  # Will return "OrderController"
    end
Aaron Rustad
sumber
ya saya melakukan itu, tetapi saya berharap dengan cara yang lebih baik. Yang saya butuhkan adalah untuk mengetahui controller mana yang telah dipanggil, tetapi saya memiliki sumber daya bersarang yang cukup rumit .. request.path_parameters ('controller') sepertinya tidak berfungsi dengan baik untuk saya.
luca
Tidak perlu self.masuk self.controller_namedanself.controller_class_name
weltschmerz
4

Jika Anda juga membutuhkan parameter :

current_fullpath = request.env ['ORIGINAL_FULLPATH']
# Jika Anda menjelajahi http://example.com/my/test/path?param_n=N 
# lalu current_fullpath akan menunjuk ke "/ my / test / path? param_n = N"

Dan ingat Anda selalu dapat memanggil <%= debug request.env %>dalam tampilan untuk melihat semua opsi yang tersedia.

DuArme
sumber
4

request.url

request.path #untuk mendapatkan path kecuali url dasar

Charles Skariah
sumber
2

Anda dapat melihat semua rute melalui rake: route (ini mungkin membantu Anda).

James Schorr
sumber
Saya lebih suka membuka tab baru dengan jalur yang tidak valid, dan melihat semua jalur / rute dari browser, karena mereka lebih cantik seperti itu. Tapi saya tidak berpikir ini membantu mendapatkan rute saat ini.
ahnbizcad
0

Anda dapat melakukan request.env['REQUEST_URI']untuk melihat URI yang diminta penuh .. itu akan menampilkan sesuatu seperti di bawah ini

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

Kamu bisa melakukan ini:

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

Sekarang, Anda dapat menggunakan seperti ini:

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