require "rails/engine" module Turbo class Engine < Rails::Engine isolate_namespace Turbo config.eager_load_namespaces << Turbo config.turbo = ActiveSupport::OrderedOptions.new config.turbo.test_connect_after_actions = %i[visit] config.autoload_once_paths = %W( #{root}/app/channels #{root}/app/controllers #{root}/app/controllers/concerns #{root}/app/helpers #{root}/app/models #{root}/app/models/concerns #{root}/app/jobs ) # If the parent application does not use Active Job, app/jobs cannot # be eager loaded, because it references the ActiveJob constant. # # When turbo-rails depends on Rails 7 or above, the entire block can be # reduced to # # unless defined?(ActiveJob) # Rails.autoloaders.once.do_not_eager_load("#{root}/app/jobs") # end # initializer "turbo.no_active_job", before: :set_eager_load_paths do unless defined?(ActiveJob) if Rails.autoloaders.zeitwerk_enabled? Rails.autoloaders.once.do_not_eager_load("#{root}/app/jobs") else # This else branch only runs in Rails 6.x + classic mode. config.eager_load_paths.delete("#{root}/app/jobs") end end end # If the parent application does not use Action Cable, app/channels cannot # be eager loaded, because it references the ActionCable constant. # # When turbo-rails depends on Rails 7 or above, the entire block can be # reduced to # # unless defined?(ActionCable) # Rails.autoloaders.once.do_not_eager_load("#{root}/app/channels") # end # initializer "turbo.no_action_cable", before: :set_eager_load_paths do unless defined?(ActionCable) if Rails.autoloaders.zeitwerk_enabled? Rails.autoloaders.once.do_not_eager_load("#{root}/app/channels") else # This else branch only runs in Rails 6.x + classic mode. config.eager_load_paths.delete("#{root}/app/channels") end end end # If you don't want to precompile Turbo's assets (eg. because you're using webpack), # you can do this in an intiailzer: # # config.after_initialize do # config.assets.precompile -= Turbo::Engine::PRECOMPILE_ASSETS # end PRECOMPILE_ASSETS = %w( turbo.js turbo.min.js turbo.min.js.map ) initializer "turbo.assets" do if Rails.application.config.respond_to?(:assets) Rails.application.config.assets.precompile += PRECOMPILE_ASSETS end end initializer "turbo.configs" do config.after_initialize do |app| Turbo.draw_routes = app.config.turbo.draw_routes != false end end initializer "turbo.helpers", before: :load_config_initializers do ActiveSupport.on_load(:action_controller_base) do include Turbo::Streams::TurboStreamsTagBuilder, Turbo::Frames::FrameRequest, Turbo::Native::Navigation helper Turbo::Engine.helpers end end initializer "turbo.request_id_tracking" do ActiveSupport.on_load(:action_controller) do include Turbo::RequestIdTracking end end initializer "turbo.broadcastable" do ActiveSupport.on_load(:active_record) do if defined?(ActiveJob) include Turbo::Broadcastable end end end initializer "turbo.mimetype" do Mime::Type.register "text/vnd.turbo-stream.html", :turbo_stream end initializer "turbo.renderer" do ActionController::Renderers.add :turbo_stream do |turbo_streams_html, options| self.content_type = Mime[:turbo_stream] if media_type.nil? turbo_streams_html end end initializer "turbo.signed_stream_verifier_key" do config.after_initialize do Turbo.signed_stream_verifier_key = config.turbo.signed_stream_verifier_key || Rails.application.key_generator.generate_key("turbo/signed_stream_verifier_key") end end initializer "turbo.test_assertions" do ActiveSupport.on_load(:active_support_test_case) do require "turbo/test_assertions" include Turbo::TestAssertions end ActiveSupport.on_load(:action_cable) do ActiveSupport.on_load(:active_support_test_case) do if defined?(ActiveJob) require "turbo/broadcastable/test_helper" include Turbo::Broadcastable::TestHelper end end end ActiveSupport.on_load(:action_dispatch_integration_test) do require "turbo/test_assertions/integration_test_assertions" include Turbo::TestAssertions::IntegrationTestAssertions end end initializer "turbo.integration_test_request_encoding" do ActiveSupport.on_load(:action_dispatch_integration_test) do # Support `as: :turbo_stream`. Public `register_encoder` API is a little too strict. class ActionDispatch::RequestEncoder class TurboStreamEncoder < IdentityEncoder header = [ Mime[:turbo_stream], Mime[:html] ].join(",") define_method(:accept_header) { header } end @encoders[:turbo_stream] = TurboStreamEncoder.new end end end initializer "turbo.system_test_helper" do ActiveSupport.on_load(:action_dispatch_system_test_case) do require "turbo/system_test_helper" include Turbo::SystemTestHelper end end config.after_initialize do |app| ActiveSupport.on_load(:action_dispatch_system_test_case) do app.config.turbo.test_connect_after_actions.map do |method| class_eval <<~RUBY, __FILE__, __LINE__ + 1 def #{method}(...) # def visit(...) super.tap { connect_turbo_cable_stream_sources } # super.tap { connect_turbo_cable_stream_sources } end # end RUBY end end end end end