跳轉到內容 跳轉到搜尋

Action Dispatch Routing UrlFor

config/routes.rb 中定義 URL 至控制器的對應,不過反過來也是可行的:可以透過其中一種路由定義產生 URL。這個模組集中處理生成 URL 的功能。

請參閱 ActionDispatch::Routing 進一步了解關於路由和 config/routes.rb 的資訊。

提示:如果您需要從模型或其他位置生成 URL,那麼 ActionDispatch::Routing::UrlFor 正是您所尋找的。繼續閱讀以取得入門說明。一般而言,此模組不應自行包含,因為通常由 url_helpers (例如 Rails.application.routes.url_helpers) 包含。

從參數產生 URL

您可能知道,一些函式,例如 ActionController::Base#url_forActionView::Helpers::UrlHelper#link_to,可以在給定一組參數的情況下產生 URL。例如,您可能曾在您的檢視中編寫過類似這樣的程式碼

<%= link_to('Click here', controller: 'users',
        action: 'new', message: 'Welcome!') %>
# => <a href="/users/new?message=Welcome%21">Click here</a>

link_to 以及所有其他需要生成 URL 功能的函式,其實在底層都使用 ActionDispatch::Routing::UrlFor。特別來說,它們使用 ActionDispatch::Routing::UrlFor#url_for 方法。可以使用以下程式碼產生與上例相同的路徑

include ActionDispatch::Routing::UrlFor
url_for(controller: 'users',
        action: 'new',
        message: 'Welcome!',
        only_path: true)
# => "/users/new?message=Welcome%21"

請注意 only_path: true 部分。這是因為 UrlFor 沒有關於您的 Rails 應用程式提供服務的主機名稱資訊。因此,如果您也想要包含主機名稱,則必須一併傳遞 :host 參數

include UrlFor
url_for(controller: 'users',
        action: 'new',
        message: 'Welcome!',
        host: 'www.example.com')
# => "http://www.example.com/users/new?message=Welcome%21"

預設情況下,所有控制器和檢視都可以存取特別版本的 url_for,這個版本已經知道目前的對應主機名稱。所以如果您在控制器或檢視中使用 url_for,則不必明確傳遞 :host 參數。

為方便起見,電子郵件函數也包含 ActionDispatch::Routing::UrlFor。因此您可以在電子郵件函數中使用 url_for。不過電子郵件函數無法存取接收到的網路要求而推測主機名稱資訊,因此您必須提供 :host 選項或使用 default_url_options 設定預設主機。更多關於在電子郵件函數中使用 url_for 的資訊,請參閱 ActionMailer::Base 文件。

為命名路由產生 URL

UrlFor 也允許存取根據命名路由自動產生的方法。例如,假設您在 config/routes.rb 中有一個「users」資源

resources :users

這會產生各種東西,包括 users_path 方法。預設情況下,您的控制器、檢視和電子郵件函數都可以存取這個方法。如果您需要從其他地方 (例如模型) 存取這個自動產生的方法,可以透過在您的類別中包含 Rails.application.routes.url_helpers 達成

class User < ActiveRecord::Base
  include Rails.application.routes.url_helpers

  def base_uri
    user_path(self)
  end
end

User.find(1).base_uri # => "/users/1"
方法
#
N
O
R
U
包含的模組

類別公用方法

new(...)

# File actionpack/lib/action_dispatch/routing/url_for.rb, line 111
def initialize(...)
  @_routes = nil
  super
end

實體公用方法

route_for(name, *args)

容許呼叫直接或正規命名路由。

resources :buckets

direct :recordable do |recording|
  route_for(:bucket, recording.bucket)
end

direct :threadable do |threadable|
  route_for(:recordable, threadable.parent)
end

此功能維護呼叫者關於是否回傳路徑或完整 URL 的內容,例如

threadable_path(threadable)  # => "/buckets/1"
threadable_url(threadable)   # => "http://example.com/buckets/1"
# File actionpack/lib/action_dispatch/routing/url_for.rb, line 222
def route_for(name, *args)
  public_send(:"#{name}_url", *args)
end

url_for(options = nil)

根據提供的選項、default_url_optionsconfig/routes.rb 中定義的路由來產生 URL。支援以下選項

  • :only_path - 如果設為 true,則會回傳相對 URL。預設為 false

  • :protocol - 連線的通訊協定。預設為 "http"

  • :host - 指定連結應該要目標的 host。如果 :only_path 為 false,則必須明確提供此選項,或透過 default_url_options 提供。

  • :subdomain - 使用 tld_length 將 subdomain 從 host 中拆分,來指定連結的 subdomain。如果為 false,則會從連結的 host 部分移除所有 subdomain。

  • :domain - 使用 tld_length 將 domain 從 host 中拆分,來指定連結的 domain。

  • :tld_length - TLD 組成的標籤數目,僅在提供 :subdomain:domain 時使用。預設為 ActionDispatch::Http::URL.tld_length,而預設值為 1。

  • :port - 選擇性地指定連線的 port。

  • :anchor - 要附加到路徑的錨定名稱。

  • :params - 要附加到路徑的查詢字串

  • :path_params - 僅用於路徑的動態區段命名的查詢字元。如果不使用,則會加以捨棄。

  • :trailing_slash - 如果設為 true,則會加入尾斜線,如 "/archive/2009/"

  • :script_name - 指定相對於 domain 根目錄的應用程式路徑。如果提供,則會加上應用程式路徑。

給予 url_for 的任何其他金鑰(:controller:action 等)都會轉發給 Routes 模組。

url_for controller: 'tasks', action: 'testing', host: 'somehost.org', port: '8080'
# => 'http://somehost.org:8080/tasks/testing'
url_for controller: 'tasks', action: 'testing', host: 'somehost.org', anchor: 'ok', only_path: true
# => '/tasks/testing#ok'
url_for controller: 'tasks', action: 'testing', trailing_slash: true
# => 'http://somehost.org/tasks/testing/'
url_for controller: 'tasks', action: 'testing', host: 'somehost.org', number: '33'
# => 'http://somehost.org/tasks/testing?number=33'
url_for controller: 'tasks', action: 'testing', host: 'somehost.org', script_name: "/myapp"
# => 'http://somehost.org/myapp/tasks/testing'
url_for controller: 'tasks', action: 'testing', host: 'somehost.org', script_name: "/myapp", only_path: true
# => '/myapp/tasks/testing'

遺失的路由金鑰可能會使用目前的請求參數填入(例如 :controller:action:id 以及任何放入路徑的其他參數)。假設目前動作已到達 GET /users/1

url_for(only_path: true)                        # => '/users/1'
url_for(only_path: true, action: 'edit')        # => '/users/1/edit'
url_for(only_path: true, action: 'edit', id: 2) # => '/users/2/edit'

請注意,第一個 url_for 呼叫未提供 :id 參數,而輔助程式使用路由路徑中的那個。任何由 url_for 暗示使用的路徑參數都可以永遠覆寫,如最後一個 url_for 呼叫所示。

# File actionpack/lib/action_dispatch/routing/url_for.rb, line 178
def url_for(options = nil)
  full_url_for(options)
end

url_options()

控制器中的掛載會覆寫以新增具有 default_url_options 的請求資訊。應用程式邏輯不應該放入 url_options。

# File actionpack/lib/action_dispatch/routing/url_for.rb, line 118
def url_options
  default_url_options
end

受保護的執行個體方法

optimize_routes_generation?()

# File actionpack/lib/action_dispatch/routing/url_for.rb, line 227
def optimize_routes_generation?
  _routes.optimize_routes_generation? && default_url_options.empty?
end

受保護的執行個體方法

_routes_context()

# File actionpack/lib/action_dispatch/routing/url_for.rb, line 239
def _routes_context # :doc:
  self
end

_with_routes(routes)

# File actionpack/lib/action_dispatch/routing/url_for.rb, line 232
def _with_routes(routes) # :doc:
  old_routes, @_routes = @_routes, routes
  yield
ensure
  @_routes = old_routes
end