Как отключить 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"включить турбо на отдельных формах.


https://github.com/hotwired/turbo/pull/419

Я опубликовал этот вопрос и ответ на 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|
Другие вопросы по тегам