Как отключить Hotwire/Turbo (замена Turbolinks) для всех форм в приложении Rails?
В Rails 7 Turbolinks заменен на Hotwire/Turbo. Это исправляет веб-ссылки, чтобы они стали запросами в стиле AJAX, как это сделали Turbolinks, но также исправляет формы. В целом, мы обнаружили, что это сломало полосу нашего приложения.
- Формы, к которым уже было привязано какое-то поведение JS, конфликтовали.
- Стандартные идиомы обработки ошибок Rails — «установить
flash
иrender :new
/render :edit
"- перерыв, поразительно; надо добавитьstatus: :unprocessable_entity
и скрестить пальцы. - Если контроллер, обрабатывающий отправку формы, перенаправляет на URL-адрес, содержащий привязку исправления (
...#foo
), Turbo раздевает его.
В конце концов, есть только так много
data: {turbo: false}
имеет смысл раскидать по всей кодовой базе. Хуже того, мы используем SimpleForm, так что это становится еще более громоздким.
html: {data: {turbo: false}}
.
Есть ли способ _глобально отключить Турбо только для форм (в идеале для всех форм, независимо от их происхождения - просто оставьте
<form>
тег и все, что внутри него, полностью отдельно, пожалуйста), но остальную часть его поведения оставить без изменений?
5 ответов
Желание исполнено, хотя и недокументировано. Доступно начиная с турбо v7.2.0 (турбо-рельсы v1.3.0).
// app/javascript/application.js
Turbo.setFormMode("on" | "off" | "optin")
"on"
- по умолчанию - Турбо формируется постоянно. Использоватьdata-turbo="false"
отключить турбо на отдельных формах.
"off"
- Никаких турбо-форм никогда. игнорируется.
"optin"
- Никаких турбо-форм, если вы не настаиваете. Использоватьdata-turbo="true"
включить турбо на отдельных формах.
Я опубликовал этот вопрос и ответ на Stack Overflow, так как не смог найти там никаких других решений. Ясно, что есть множество недостатков, и я бы предпочел увидеть простой флаг конфигурации для Turbo, который заставил бы его игнорировать формы — это был бы чрезвычайно предпочтительный подход.
У меня все еще нет полного решения в любом случае, потому что формы, созданные внутри Rails, например, для a, все еще являются проблемой, но я все же обошел некоторые из них, используя некоторые патчи для обезьян.
С одной стороны есть формы Rails:
- Судя по всему,
data-turbo
значение атрибута яблоки для этого узла и всех дочерних элементов , поэтому можно обернуть, например, сгенерированную Rails «динамическую» форму, например, изlink_to(...method: delete)
в DIV с этим набором атрибутов и, по крайней мере, обходить эти проблемы в каждом конкретном случае - хотя обратите внимание, у меня все еще возникают проблемы с выполнением этой работы в некоторых случаях. - Однако, если у вас их много, это будет навязчиво и уродливо, поэтому было бы неплохо иметь способ заставить Turbo просто полностью игнорировать формы.
С другой стороны, есть формы SimpleForm:
- SimpleForm не предоставляет возможности глобальной настройки атрибутов данных, которые будут добавлены в
form
элементы, которые он строит. Предыдущие запросы на это в проблемах GitHub до сих пор были явно отклонены. - Похоже, что SimpleForm не дает возможности настроить оболочку, которая бы обходила форму в целом, а только настраиваемые оболочки для входных данных внутри формы. Таким образом, мы не можем просто, например, написать оболочку DIV, как упоминалось выше.
Мне довелось участвовать в драгоценном камне под названием Hoodoo , который предоставляет средства исправления обезьян, которые позволяют вам писать модули исправления, которые больше похожи на подклассы -
super
доступен для вызова исправленной реализации - и, кроме того, исправления могут быть включены или отключены динамически и легко. Hoodoo на самом деле является фреймворком службы приложений Rack, так что это что-то вроде кувалды - я всегда намеревался однажды извлечь это в свой собственный гем, но на момент написания я не дошел до этого (а прошло несколько лет). по) - но мы можем
require
только часть, которая нам нужна, и игнорировать остальные.
Здесь я исправляю методы компоновщика SimpleForm. Они просто вызывают хелперы формы Rails под капотом, поэтому вместо этого я мог бы попытаться исправить более низкие уровни в Rails, но в любом случае следующее сработало.
В твоей
Gemfile
, объявите зависимость Hoodoo, но не загружайте все ее составные части, так как большинство из них вам не понадобится.
# Hoodoo's monkey patch module is useful sometimes:
# https://rubygems.org/gems/hoodoo
#
# MUST use 'require: false' so that the Rack components of Hoodoo middleware
# do not get activated; this is a Rails app, not a Hoodoo service!
#
gem 'hoodoo', '~> 2.12', require: false
... затем напишите что-то вроде
config/initializers/simple_form_monkey_patch.rb
который выглядит примерно так:
require 'hoodoo/monkey'
module SimpleFormMonkey
module InstanceExtensions
def simple_form_for(record, options = {}, &block)
modified_options = {html: {data: {turbo: false}}}
modified_options.deep_merge!(options)
super(record, modified_options, &block)
end
end
end
Hoodoo::Monkey.register(
extension_module: SimpleFormMonkey,
target_unit: SimpleForm::ActionViewExtensions::FormHelper
)
Hoodoo::Monkey.enable(
extension_module: SimpleFormMonkey
)
... это сделает это. Это имеет некоторый риск, поскольку мы исправляем вещи, которые — с точки зрения имени модуля и вложенности — технически закрыты для SimpleForm, но сама сигнатура метода, по крайней мере, общедоступна. Вы можете исправить
ActionView::Helpers::FormHelper
с переопределением для
form_for
вместо этого, если вы хотите перейти на более низкий уровень и исправить API, который был стабильным в течение очень долгого времени. Код будет почти идентичен, так как сигнатуры методов одинаковы.
Я использовал Javascript для решения этой проблемы:
document.querySelectorAll('form').forEach(function (el) {
el.dataset.turbo = false
})
Больше никаких нестабильных системных тестов из-за случайного отсутствия флэш-сообщений/предупреждений после отправки формы, и Devise снова работает отлично.
Вы можете отключитьturbo drive
добавив эти строки в свойapplication.js
:
import { Turbo } from "@hotwired/turbo-rails"
Turbo.session.drive = false
Дополнительная информация: https://turbo.hotwired.dev/handbook/drive#disabling-turbo-drive-on-specific-links-or-forms .
@kamilpogo ваше решение сработало как шарм! ты!!! в настоящее время изучаю и следую этому руководству по GoRails, прежде чем столкнулся с некоторыми проблемами с турбо, пытаясь отобразить «Спасибо!» для кого-либо еще там.
в основном, я добавил javascript в /layouts/application.html.erb, как показано ниже:
<script>
document.querySelectorAll('form').forEach(function (el) {
el.dataset.turbo = false
})
</script>
<script src="js-bootstrap"></script>
</body>
</html>
ОБНОВЛЕНИЕ: комментарии в видео имеют другую работу, устанавливая для турбо значение «ложь», а для локального значения «истина» внутри формы:
form_with model: @user, url: sign_up_path, local: true, data: { turbo:false } do |form|