модуль ActionDispatch::Routing::UrlFor
В config/routes.rb вы определяете сопоставления URL с контроллерами, но обратное также возможно: URL можно сгенерировать по одному из ваших определений маршрутов. Функциональность генерации URL централизована в этом модуле.
См. ActionDispatch::Routing для общей информации о маршрутизации и файле routes.rb.
Подсказка: Если вам нужно генерировать URL из ваших моделей или из какого-то другого места, то вам нужно использовать ActionController::UrlFor. Читайте далее для ознакомления. Как правило, этот модуль не следует включать самостоятельно, так как он обычно включается url_helpers (как в Rails.application.routes.url_helpers).
Генерация URL из параметров
Как вы знаете, некоторые функции, такие как ActionController::Base#url_for и ActionView::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, на самом деле используют ActionController::UrlFor под капотом. И, в частности, они используют метод ActionController::UrlFor#url_for. Можно сгенерировать тот же путь, что и в примере выше, используя следующий код:
include 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 аргумент.
Для удобства, письма содержат сокращение для ActionController::UrlFor#url_for. Поэтому внутри писем вам нужно написать только url_for вместо 'ActionController::UrlFor#url_for' полностью. Однако у писем нет информации о хостном имени, и вам все равно нужно предоставить :host аргумент или установить значение по умолчанию для хоста, которое будет использоваться во всех письмах, используя параметр конфигурации config.action_mailer.default_url_options. Для получения дополнительной информации об #url_for в письмах, прочитайте документацию ActionMailer#Base.
Генерация URL для именованных маршрутов
UrlFor также позволяет получить доступ к методам, которые были сгенерированы автоматически из именованных маршрутов. Например, предположим, что у вас есть ресурс «пользователи» в вашей config/routes.rb:
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"
Публичные методы класса
# File actionpack/lib/action_dispatch/routing/url_for.rb, line 104 def initialize(*) @_routes = nil super end
Публичные методы экземпляра
# File actionpack/lib/action_dispatch/routing/url_for.rb, line 166
def url_for(options = nil)
case options
when nil
_routes.url_for(url_options.symbolize_keys)
when Hash
route_name = options.delete :use_route
_routes.url_for(options.symbolize_keys.reverse_merge!(url_options),
route_name)
when ActionController::Parameters
unless options.permitted?
raise ArgumentError.new(ActionDispatch::Routing::INSECURE_URL_PARAMETERS_MESSAGE)
end
route_name = options.delete :use_route
_routes.url_for(options.to_h.symbolize_keys.
reverse_merge!(url_options), route_name)
when String
options
when Symbol
HelperMethodBuilder.url.handle_string_call self, options
when Array
components = options.dup
polymorphic_url(components, components.extract_options!)
when Class
HelperMethodBuilder.url.handle_class_call self, options
else
HelperMethodBuilder.url.handle_model_call self, options
end
end Генерирует URL на основе предоставленных параметров, default_url_options и маршрутов, определенных в routes.rb. Поддерживаются следующие параметры:
-
:only_path- Если true, возвращается относительный URL. По умолчаниюfalse. -
:protocol- Протокол подключения. По умолчанию 'http'. -
:host- Указывает хост, на который должен быть нацелен link. Если:only_pathfalse, этот параметр должен быть предоставлен явно или черезdefault_url_options. -
:subdomain- Указывает поддомен link, используяtld_lengthдля разделения поддомена от хоста. Если false, удаляет все поддомены из части хоста link. -
:domain- Указывает домен link, используяtld_lengthдля разделения домена от хоста. -
:tld_length- Количество метков, из которых состоит TLD, используется только если:subdomainили:domainуказаны. По умолчаниюActionDispatch::Http::URL.tld_length, которое, в свою очередь, по умолчанию равно 1. -
:port- Дополнительно укажите порт для подключения. -
:anchor- Имя якоря, которое нужно добавить к пути. -
:trailing_slash- Если true, добавляет конечную косую черту, как в «/archive/2009/» -
:script_name- Указывает путь приложения относительно корня домена. Если указано, добавляет путь приложения.
Любой другой ключ (:controller, :action, и т.д.) предоставленный url_for передаётся в модуль маршрутов.
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'
Обратите внимание, что параметр :id не был предоставлен в первом вызове url_for и помощник использовал параметр из пути маршрута. Любой параметр пути, неявно используемый url_for всегда может быть перезаписан, как показано на последних url_for вызовах.
# File actionpack/lib/action_dispatch/routing/url_for.rb, line 112 def url_options default_url_options end
Переопределенный в контроллере метод для добавления информации о запросе с помощью `default_url_options`. Логика приложения не должна содержаться в url_options.
Защищенные методы экземпляра
# File actionpack/lib/action_dispatch/routing/url_for.rb, line 208 def _routes_context self end
# File actionpack/lib/action_dispatch/routing/url_for.rb, line 201 def _with_routes(routes) old_routes, @_routes = @_routes, routes yield ensure @_routes = old_routes end
# File actionpack/lib/action_dispatch/routing/url_for.rb, line 197 def optimize_routes_generation? _routes.optimize_routes_generation? && default_url_options.empty? end
© 2004–2018 David Heinemeier Hansson
Licensed under the MIT License.