跳至内容 跳至搜索

Action Dispatch Routing UrlFor

config/routes.rb 中,您定义了 URL 到控制器的映射,但反过来也是可能的:可以从您的路由定义之一生成 URL。URL 生成功能集中在这个模块中。

有关路由和 config/routes.rb 的一般信息,请参见 ActionDispatch::Routing

提示:如果您需要从模型或其他地方生成 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。但是,邮件程序无法访问传入的 Web 请求以获取主机名信息,因此您必须提供: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 108
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 217
def route_for(name, *args)
  public_send(:"#{name}_url", *args)
end

url_for(options = nil)

根据提供的选项、default_url_optionsconfig/routes.rb中定义的路由生成 URL。支持以下选项

  • :only_path - 如果为真,则返回相对 URL。默认为false

  • :protocol - 连接的协议。默认为"http"

  • :host - 指定链接应指向的主机。如果:only_path为假,则必须通过显式提供或通过default_url_options提供此选项。

  • :subdomain - 指定链接的子域,使用tld_length将子域与主机分开。如果为假,则从链接的主机部分中删除所有子域。

  • :domain - 使用 tld_length 将域名从主机名中分离,指定链接的域名。

  • :tld_length - TLD ID 由多少个标签组成,仅在提供 :subdomain:domain 时使用。默认值为 ActionDispatch::Http::URL.tld_length,该值默认为 1。

  • :port - 可选地指定要连接的端口。

  • :anchor - 要附加到路径的锚点名称。

  • :params - 要附加到路径的查询参数。

  • :path_params - 仅用于路径的命名动态段的查询参数。如果未使用,它们将被丢弃。

  • :trailing_slash - 如果为 true,则添加尾部斜杠,例如 "/archive/2009/"

  • :script_name - 指定相对于域名根目录的应用程序路径。如果提供,则在前面加上应用程序路径。

传递给 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 参数,助手使用了来自路由路径的 :id 参数。任何由 url_for 隐式使用的路径参数都可以像最后几个 url_for 调用中所示的那样被覆盖。

# File actionpack/lib/action_dispatch/routing/url_for.rb, line 173
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 116
def url_options
  default_url_options
end

实例保护方法

optimize_routes_generation?()

# File actionpack/lib/action_dispatch/routing/url_for.rb, line 222
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 234
def _routes_context # :doc:
  self
end

_with_routes(routes)

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