модуль ActionView::Helpers::UrlHelper
Справочник по URL-помощникам Action View
Предоставляет набор методов для создания ссылок и получения URL-адресов, зависящих от подсистемы маршрутизации (см. ActionDispatch::Routing). Это позволяет использовать один и тот же формат для ссылок в представлениях и контроллерах.
Константы
- BUTTON_TAG_METHOD_VERBS
-
Этот помощник может быть включён в любой класс, включающий помощники URL маршрутов (routes.url_helpers). Некоторые методы, представленные здесь, будут работать только в контексте запроса (
link_to_unless_current, например), который должен быть предоставлен как метод, называемый request в контексте. - STRINGIFIED_COMMON_METHODS
Методы общедоступного экземпляра
# File actionview/lib/action_view/helpers/url_helper.rb, line 296
def button_to(name = nil, options = nil, html_options = nil, &block)
html_options, options = options, name if block_given?
html_options ||= {}
html_options = html_options.stringify_keys
url =
case options
when FalseClass then nil
else url_for(options)
end
remote = html_options.delete("remote")
params = html_options.delete("params")
authenticity_token = html_options.delete("authenticity_token")
method = (html_options.delete("method").presence || method_for_options(options)).to_s
method_tag = BUTTON_TAG_METHOD_VERBS.include?(method) ? method_tag(method) : "".html_safe
form_method = method == "get" ? "get" : "post"
form_options = html_options.delete("form") || {}
form_options[:class] ||= html_options.delete("form_class") || "button_to"
form_options[:method] = form_method
form_options[:action] = url
form_options[:'data-remote'] = true if remote
request_token_tag = if form_method == "post"
request_method = method.empty? ? "post" : method
token_tag(authenticity_token, form_options: { action: url, method: request_method })
else
""
end
html_options = convert_options_to_data_attributes(options, html_options)
html_options["type"] = "submit"
button = if block_given?
content_tag("button", html_options, &block)
elsif button_to_generates_button_tag
content_tag("button", name || url, html_options, &block)
else
html_options["value"] = name || url
tag("input", html_options)
end
inner_tags = method_tag.safe_concat(button).safe_concat(request_token_tag)
if params
to_form_params(params).each do |param|
inner_tags.safe_concat tag(:input, type: "hidden", name: param[:name], value: param[:value],
autocomplete: "off")
end
end
html = content_tag("form", inner_tags, form_options)
prevent_content_exfiltration(html)
end Генерирует форму, содержащую одну кнопку, которая отправляет запрос на URL, созданный набором options. Это самый безопасный метод для того, чтобы ссылки, вызывающие изменения в ваших данных, не запускались ботами или ускорителями поиска.
Вы можете управлять поведением формы и кнопки с помощью html_options. Большинство значений в html_options передаются в элемент кнопки. Например, передача параметра :class в html_options установит атрибут класса элемента кнопки.
Атрибут класса элемента формы можно задать, передав параметр :form_class в html_options. По умолчанию используется "button_to" для форматирования формы и её дочерних элементов.
Форма по умолчанию отправляет POST-запрос, если объект не сохранён; наоборот, если объект сохранён, он отправит PATCH-запрос. Чтобы указать другой HTTP-глагол, используйте параметр :method в html_options.
Если HTML-кнопка, сгенерированная из button_to, не работает с вашей макетом, вы можете рассмотреть использование метода link_to с атрибутом data-turbo-method, как описано в документации link_to.
Параметры
Хэш options принимает те же параметры, что и url_for. Чтобы сгенерировать элемент <form> без атрибута [action], передайте false:
<%= button_to "New", false %> # => "<form method="post" class="button_to"> # <button type="submit">New</button> # <input name="authenticity_token" type="hidden" value="10f2163b45388899ad4d5ae948988266befcb6c3d1b2451cf657a0c293d605a6"/> # </form>"
Большинство значений в html_options передаются в элемент кнопки, но есть несколько специальных параметров:
-
:method- Символ HTTP-глагола. Поддерживаемые глаголы -:post,:get,:delete,:patch, и:put. По умолчанию он будет:post. -
:disabled- Если установлено в true, генерируется отключенная кнопка. -
:data- Этот параметр можно использовать для добавления пользовательских атрибутов данных. -
:form- Этот хэш будет атрибутами формы. -
:form_class- Этот параметр определяет класс формы, в которую будет помещена кнопка отправки. -
:params- Хэш параметров, которые будут отображаться как скрытые поля в форме.
Примеры
<%= button_to "New", action: "new" %>
# => "<form method="post" action="/controller/new" class="button_to">
# <button type="submit">New</button>
# <input name="authenticity_token" type="hidden" value="10f2163b45388899ad4d5ae948988266befcb6c3d1b2451cf657a0c293d605a6" autocomplete="off"/>
# </form>"
<%= button_to "New", new_article_path %>
# => "<form method="post" action="/articles/new" class="button_to">
# <button type="submit">New</button>
# <input name="authenticity_token" type="hidden" value="10f2163b45388899ad4d5ae948988266befcb6c3d1b2451cf657a0c293d605a6" autocomplete="off"/>
# </form>"
<%= button_to "New", new_article_path, params: { time: Time.now } %>
# => "<form method="post" action="/articles/new" class="button_to">
# <button type="submit">New</button>
# <input name="authenticity_token" type="hidden" value="10f2163b45388899ad4d5ae948988266befcb6c3d1b2451cf657a0c293d605a6"/>
# <input type="hidden" name="time" value="2021-04-08 14:06:09 -0500" autocomplete="off">
# </form>"
<%= button_to [:make_happy, @user] do %>
Make happy <strong><%= @user.name %></strong>
<% end %>
# => "<form method="post" action="/users/1/make_happy" class="button_to">
# <button type="submit">
# Make happy <strong><%= @user.name %></strong>
# </button>
# <input name="authenticity_token" type="hidden" value="10f2163b45388899ad4d5ae948988266befcb6c3d1b2451cf657a0c293d605a6" autocomplete="off"/>
# </form>"
<%= button_to "New", { action: "new" }, form_class: "new-thing" %>
# => "<form method="post" action="/controller/new" class="new-thing">
# <button type="submit">New</button>
# <input name="authenticity_token" type="hidden" value="10f2163b45388899ad4d5ae948988266befcb6c3d1b2451cf657a0c293d605a6" autocomplete="off"/>
# </form>"
<%= button_to "Create", { action: "create" }, form: { "data-type" => "json" } %>
# => "<form method="post" action="/images/create" class="button_to" data-type="json">
# <button type="submit">Create</button>
# <input name="authenticity_token" type="hidden" value="10f2163b45388899ad4d5ae948988266befcb6c3d1b2451cf657a0c293d605a6" autocomplete="off"/>
# </form>" # File actionview/lib/action_view/helpers/url_helper.rb, line 548
def current_page?(options = nil, check_parameters: false, **options_as_kwargs)
unless request
raise "You cannot use helpers that need to determine the current " \
"page unless your view context provides a Request object " \
"in a #request method"
end
return false unless request.get? || request.head?
options ||= options_as_kwargs
check_parameters ||= options.is_a?(Hash) && options.delete(:check_parameters)
url_string = URI::RFC2396_PARSER.unescape(url_for(options)).force_encoding(Encoding::BINARY)
# We ignore any extra parameters in the request_uri if the
# submitted URL doesn't have any either. This lets the function
# work with things like ?order=asc
# the behavior can be disabled with check_parameters: true
request_uri = url_string.index("?") || check_parameters ? request.fullpath : request.path
request_uri = URI::RFC2396_PARSER.unescape(request_uri).force_encoding(Encoding::BINARY)
if %r{^\w+://}.match?(url_string)
request_uri = +"#{request.protocol}#{request.host_with_port}#{request_uri}"
end
remove_trailing_slash!(url_string)
remove_trailing_slash!(request_uri)
url_string == request_uri
end True, если текущий URI запроса был сгенерирован заданным options.
Примеры
Предположим, мы находимся в действии http://www.example.com/shop/checkout?order=desc&page=1.
current_page?(action: 'process')
# => false
current_page?(action: 'checkout')
# => true
current_page?(controller: 'library', action: 'checkout')
# => false
current_page?(controller: 'shop', action: 'checkout')
# => true
current_page?(controller: 'shop', action: 'checkout', order: 'asc')
# => false
current_page?(controller: 'shop', action: 'checkout', order: 'desc', page: '1')
# => true
current_page?(controller: 'shop', action: 'checkout', order: 'desc', page: '2')
# => false
current_page?('http://www.example.com/shop/checkout')
# => true
current_page?('http://www.example.com/shop/checkout', check_parameters: true)
# => false
current_page?('/shop/checkout')
# => true
current_page?('http://www.example.com/shop/checkout?order=desc&page=1')
# => true
Предположим, мы находимся в действии http://www.example.com/products с методом POST в случае невалидного продукта.
current_page?(controller: 'product', action: 'index') # => false
Мы также можем передать символические аргументы вместо строк.
# File actionview/lib/action_view/helpers/url_helper.rb, line 198
def link_to(name = nil, options = nil, html_options = nil, &block)
html_options, options, name = options, name, block if block_given?
options ||= {}
html_options = convert_options_to_data_attributes(options, html_options)
url = url_target(name, options)
html_options["href"] ||= url
content_tag("a", name || url, html_options, &block)
end Создаёт элемент якоря с заданным name используя URL, созданный набором options. Смотрите допустимые параметры в документации для url_for. Также можно передать строку вместо хэша параметров, что создаёт элемент якоря, использующий значение строки в качестве href ссылки. Использование символического :back вместо хэша параметров сгенерирует ссылку на referrer (JavaScript back link будет использован вместо referrer, если он не существует). Если nil передаётся в качестве имени, значение самой ссылки станет именем.
Подписи
link_to(body, url, html_options = {})
# url is a String; you can use URL helpers like
# posts_path
link_to(body, url_options = {}, html_options = {})
# url_options, except :method, is passed to url_for
link_to(options = {}, html_options = {}) do
# name
end
link_to(url, html_options = {}) do
# name
end
link_to(active_record_model)
Параметры
-
:data- Этот параметр можно использовать для добавления пользовательских атрибутов данных.
Примеры
Поскольку она полагается на url_for, link_to поддерживает как старые аргументы контроллер/действие/id, так и новые RESTful маршруты. Текущий стиль Rails отдаёт предпочтение RESTful маршрутам, когда это возможно, поэтому используйте базовые ресурсы и
link_to "Profile", profile_path(@profile) # => <a href="/profiles/1">Profile</a>
или даже более краткое
link_to "Profile", @profile # => <a href="/profiles/1">Profile</a>
вместо более длинного, устаревшего, не ориентированного на ресурсы
link_to "Profile", controller: "profiles", action: "show", id: @profile # => <a href="/profiles/show/1">Profile</a>
Аналогично,
link_to "Profiles", profiles_path # => <a href="/profiles">Profiles</a>
лучше чем
link_to "Profiles", controller: "profiles" # => <a href="/profiles">Profiles</a>
Когда имя - nil, отображается href вместо него
link_to nil, "http://example.com" # => <a href="http://www.example.com">http://www.example.com</a>
Более лаконично, когда name является моделью Active Record, которая определяет метод to_s возвращающий значение по умолчанию или атрибут модели экземпляра
link_to @profile # => <a href="http://www.example.com/profiles/1">Eileen</a>
Вы также можете использовать блок, если цель ссылки трудно вписать в параметр имени. ERB пример:
<%= link_to(@profile) do %>
<strong><%= @profile.name %></strong> -- <span>Check it out!</span>
<% end %>
# => <a href="/profiles/1">
<strong>David</strong> -- <span>Check it out!</span>
</a> Классы и id для CSS легко создать:
link_to "Articles", articles_path, id: "news", class: "article" # => <a href="/articles" class="article" id="news">Articles</a>
Будьте осторожны при использовании устаревшего стиля аргументов, поскольку требуется дополнительный буквальный хэш:
link_to "Articles", { controller: "articles" }, id: "news", class: "article"
# => <a href="/articles" class="article" id="news">Articles</a>
Если опустить хэш, получится неверная ссылка:
link_to "WRONG!", controller: "articles", id: "news", class: "article" # => <a href="/articles/index/news?class=article">WRONG!</a>
link_to также может создавать ссылки с анкорами или параметрами запроса:
link_to "Comment wall", profile_path(@profile, anchor: "wall") # => <a href="/profiles/1#wall">Comment wall</a> link_to "Ruby on Rails search", controller: "searches", query: "ruby on rails" # => <a href="/searches?query=ruby+on+rails">Ruby on Rails search</a> link_to "Nonsense search", searches_path(foo: "bar", baz: "quux") # => <a href="/searches?foo=bar&baz=quux">Nonsense search</a>
Вы можете установить любые атрибуты ссылки, такие как target, rel, type:
link_to "External link", "http://www.rubyonrails.org/", target: "_blank", rel: "nofollow" # => <a href="http://www.rubyonrails.org/" target="_blank" rel="nofollow">External link</a>
Turbo
Rails 7 поставляется с включённой по умолчанию поддержкой Turbo. Turbo предоставляет следующие :data параметры:
-
turbo_method: symbol of HTTP verb- Выполняет посещение Turbo с заданным HTTP-глаголом. Рекомендуется использовать формы при выполнении запросов, отличных отGET. Используйтеdata-turbo-methodтолько в тех случаях, когда форма невозможна. -
turbo_confirm: "question?"- Добавляет диалог подтверждения к ссылке со значением.
Обратитесь к Руководству по Turbo, чтобы получить дополнительную информацию об указанных параметрах.
Примеры
link_to "Delete profile", @profile, data: { turbo_method: :delete }
# => <a href="/profiles/1" data-turbo-method="delete">Delete profile</a>
link_to "Visit Other Site", "https://rubyonrails.org/", data: { turbo_confirm: "Are you sure?" }
# => <a href="https://rubyonrails.org/" data-turbo-confirm="Are you sure?">Visit Other Site</a>
# File actionview/lib/action_view/helpers/url_helper.rb, line 437
def link_to_if(condition, name, options = {}, html_options = {}, &block)
if condition
link_to(name, options, html_options)
else
if block_given?
block.arity <= 1 ? capture(name, &block) : capture(name, options, html_options, &block)
else
ERB::Util.html_escape(name)
end
end
end Создаёт тег ссылки с заданным name используя URL, созданный набором options если condition равно true, иначе возвращается только имя. Для специализации поведения по умолчанию можно передать блок, который принимает имя или весь список аргументов для link_to_if.
Примеры
<%= link_to_if(@current_user.nil?, "Login", { controller: "sessions", action: "new" }) %>
# If the user isn't logged in...
# => <a href="/sessions/new/">Login</a>
<%=
link_to_if(@current_user.nil?, "Login", { controller: "sessions", action: "new" }) do
link_to(@current_user.login, { controller: "accounts", action: "show", id: @current_user })
end
%>
# If the user isn't logged in...
# => <a href="/sessions/new/">Login</a>
# If they are logged in...
# => <a href="/accounts/show/3">my_username</a> # File actionview/lib/action_view/helpers/url_helper.rb, line 414
def link_to_unless(condition, name, options = {}, html_options = {}, &block)
link_to_if !condition, name, options, html_options, &block
end Создаёт тег ссылки с заданным name используя URL, созданный набором options если condition не равно true, в противном случае возвращается только имя. Чтобы специализировать поведение по умолчанию (например, отображать ссылку входа вместо просто текста ссылки), можно передать блок, который принимает имя или весь список аргументов для link_to_unless.
Примеры
<%= link_to_unless(@current_user.nil?, "Reply", { action: "reply" }) %>
# If the user is logged in...
# => <a href="/controller/reply/">Reply</a>
<%=
link_to_unless(@current_user.nil?, "Reply", { action: "reply" }) do |name|
link_to(name, { controller: "accounts", action: "signup" })
end
%>
# If the user is logged in...
# => <a href="/controller/reply/">Reply</a>
# If not...
# => <a href="/accounts/signup">Reply</a> # File actionview/lib/action_view/helpers/url_helper.rb, line 390
def link_to_unless_current(name, options = {}, html_options = {}, &block)
link_to_unless current_page?(options), name, options, html_options, &block
end Создаёт тег ссылки с заданным name используя URL, созданный набором options если текущий URI запроса отличается от ссылок, в противном случае возвращается только имя (или указанный блок, если он существует). Вы можете передать link_to_unless_current блок, который специализирует поведение по умолчанию (например, отображать ссылку «Начать здесь» вместо текста ссылки).
Примеры
Предположим, у вас есть навигационное меню…
<ul id="navbar">
<li><%= link_to_unless_current("Home", { action: "index" }) %></li>
<li><%= link_to_unless_current("About Us", { action: "about" }) %></li>
</ul> Если мы находимся в действии «о нас», отобразится…
<ul id="navbar"> <li><a href="/controller/index">Home</a></li> <li>About Us</li> </ul>
…но если в действии «индекс», отобразится:
<ul id="navbar"> <li>Home</li> <li><a href="/controller/about">About Us</a></li> </ul>
Неявный блок, переданный link_to_unless_current оценивается, если текущее действие совпадает с заданным действием. Так, если у нас есть страница комментариев и мы хотим отобразить ссылку «Назад», вместо ссылки на страницу комментариев, мы можем сделать что-то вроде этого…
<%=
link_to_unless_current("Comment", { controller: "comments", action: "new" }) do
link_to("Go back", { controller: "posts", action: "index" })
end
%> # File actionview/lib/action_view/helpers/url_helper.rb, line 487
def mail_to(email_address, name = nil, html_options = {}, &block)
html_options, name = name, nil if name.is_a?(Hash)
html_options = (html_options || {}).stringify_keys
extras = %w{ cc bcc body subject reply_to }.map! { |item|
option = html_options.delete(item).presence || next
"#{item.dasherize}=#{ERB::Util.url_encode(option)}"
}.compact
extras = extras.empty? ? "" : "?" + extras.join("&")
encoded_email_address = ERB::Util.url_encode(email_address).gsub("%40", "@")
html_options["href"] = "mailto:#{encoded_email_address}#{extras}"
content_tag("a", name || email_address, html_options, &block)
end Создаёт тег ссылки mailto для указанного email_address, который также используется в качестве имени ссылки, если не указан name. Дополнительные атрибуты HTML для ссылки можно передать в html_options.
mail_to имеет несколько методов для настройки самого письма путём передачи специальных ключей в html_options.
Параметры
-
:subject- Установка темы письма. -
:body- Установка тела письма. -
:cc- Добавление дополнительных получателей в поле Копия. -
:bcc- Добавление дополнительных получателей в поле Скрытая копия. -
:reply_to- Установка поляReply-Toписьма.
Защита от сбора адресов
До Rails 4.0 mail_to предоставлял параметры для кодирования адреса, чтобы затруднить сбор электронных адресов. Чтобы воспользоваться этими параметрами, установите gem actionview-encoded_mail_to.
Примеры
mail_to "me@domain.com"
# => <a href="mailto:me@domain.com">me@domain.com</a>
mail_to "me@domain.com", "My email"
# => <a href="mailto:me@domain.com">My email</a>
mail_to "me@domain.com", cc: "ccaddress@domain.com",
subject: "This is an example email"
# => <a href="mailto:me@domain.com?cc=ccaddress@domain.com&subject=This%20is%20an%20example%20email">me@domain.com</a>
Можно использовать блок, если ссылка сложна для отображения в параметре имени. ERB пример:
<%= mail_to "me@domain.com" do %>
<strong>Email me:</strong> <span>me@domain.com</span>
<% end %>
# => <a href="mailto:me@domain.com">
<strong>Email me:</strong> <span>me@domain.com</span>
</a> # File actionview/lib/action_view/helpers/url_helper.rb, line 669
def phone_to(phone_number, name = nil, html_options = {}, &block)
html_options, name = name, nil if name.is_a?(Hash)
html_options = (html_options || {}).stringify_keys
country_code = html_options.delete("country_code").presence
country_code = country_code.nil? ? "" : "+#{ERB::Util.url_encode(country_code)}"
encoded_phone_number = ERB::Util.url_encode(phone_number)
html_options["href"] = "tel:#{country_code}#{encoded_phone_number}"
content_tag("a", name || phone_number, html_options, &block)
end Создаёт тег ссылки TEL для указанного phone_number. При нажатии ссылки открывается приложение для совершения звонков и предварительно заполняется номер телефона.
Если name не указан, то phone_number используется в качестве имени ссылки.
Поддерживается параметр country_code, который добавляет знак «плюс» и указанный код страны к номеру телефона. Например, country_code: "01" добавит +01 к номеру телефона.
Дополнительные атрибуты HTML для ссылки можно передать через html_options.
Параметры
-
:country_code- Добавляет код страны к номеру телефона
Примеры
phone_to "1234567890" # => <a href="tel:1234567890">1234567890</a> phone_to "1234567890", "Phone me" # => <a href="tel:1234567890">Phone me</a> phone_to "1234567890", country_code: "01" # => <a href="tel:+011234567890">1234567890</a>
Можно использовать блок, если ссылка сложна для отображения в параметре имени. Пример с ERB:
<%= phone_to "1234567890" do %>
<strong>Phone me:</strong>
<% end %>
# => <a href="tel:1234567890">
<strong>Phone me:</strong>
</a> # File actionview/lib/action_view/helpers/url_helper.rb, line 618
def sms_to(phone_number, name = nil, html_options = {}, &block)
html_options, name = name, nil if name.is_a?(Hash)
html_options = (html_options || {}).stringify_keys
country_code = html_options.delete("country_code").presence
country_code = country_code ? "+#{ERB::Util.url_encode(country_code)}" : ""
body = html_options.delete("body").presence
body = body ? "?&body=#{ERB::Util.url_encode(body)}" : ""
encoded_phone_number = ERB::Util.url_encode(phone_number)
html_options["href"] = "sms:#{country_code}#{encoded_phone_number};#{body}"
content_tag("a", name || phone_number, html_options, &block)
end Создаёт тег ссылки SMS для указанного phone_number. При нажатии ссылки открывается приложение для отправки SMS, готовое отправить сообщение на указанный номер телефона. Если указан параметр body, содержимое сообщения будет установлено в body.
Если name не указан, то phone_number используется в качестве имени ссылки.
Поддерживается параметр country_code, который добавляет знак «плюс» и указанный код страны к номеру телефона. Например, country_code: "01" добавит +01 к номеру телефона.
Дополнительные атрибуты HTML для ссылки можно передать через html_options.
Параметры
-
:country_code- Добавить код страны к номеру телефона. -
:body- Установить содержимое сообщения.
Примеры
sms_to "5155555785" # => <a href="sms:5155555785;">5155555785</a> sms_to "5155555785", country_code: "01" # => <a href="sms:+015155555785;">5155555785</a> sms_to "5155555785", "Text me" # => <a href="sms:5155555785;">Text me</a> sms_to "5155555785", body: "I have a question about your product." # => <a href="sms:5155555785;?body=I%20have%20a%20question%20about%20your%20product">5155555785</a>
Можно использовать блок, если ссылка сложна для отображения в параметре имени. Пример с ERB:
<%= sms_to "5155555785" do %>
<strong>Text me:</strong>
<% end %>
# => <a href="sms:5155555785;">
<strong>Text me:</strong>
</a>
© 2004–2021 David Heinemeier Hansson
Licensed under the MIT License.