Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Avoid eager loading Turbo Ruby files #3687

Closed
wants to merge 1 commit into from

Conversation

jdufresne
Copy link
Member

Some projects use RailsAdmin without using Turbo or ActionCable. In these applications, when the Rails configuration option config.eager_load is set to true, the RailsAdmin requirement of turbo will result in eager loading files that can't load.

The result is the following error:

.../vendor/bundle/ruby/3.3.0/gems/turbo-rails-2.0.5/app/channels/turbo/streams_channel.rb:34:in `<top (required)>': uninitialized constant ActionCable (NameError)

class Turbo::StreamsChannel < ActionCable::Channel::Base
                              ^^^^^^^^^^^
Did you mean?  ActionMailer
	from /home/jon/.rubies/ruby-3.3.2/lib/ruby/3.3.0/bundled_gems.rb:74:in `require'
	from /home/jon/.rubies/ruby-3.3.2/lib/ruby/3.3.0/bundled_gems.rb:74:in `block (2 levels) in replace_require'
	from .../vendor/bundle/ruby/3.3.0/gems/zeitwerk-2.6.14/lib/zeitwerk/kernel.rb:26:in `require'
	from .../vendor/bundle/ruby/3.3.0/gems/zeitwerk-2.6.14/lib/zeitwerk/loader/helpers.rb:139:in `const_get'
	from .../vendor/bundle/ruby/3.3.0/gems/zeitwerk-2.6.14/lib/zeitwerk/loader/helpers.rb:139:in `cget'
	from .../vendor/bundle/ruby/3.3.0/gems/zeitwerk-2.6.14/lib/zeitwerk/loader/eager_load.rb:175:in `block in actual_eager_load_dir'
	from .../vendor/bundle/ruby/3.3.0/gems/zeitwerk-2.6.14/lib/zeitwerk/loader/helpers.rb:42:in `block in ls'
	from .../vendor/bundle/ruby/3.3.0/gems/zeitwerk-2.6.14/lib/zeitwerk/loader/helpers.rb:25:in `each'
	from .../vendor/bundle/ruby/3.3.0/gems/zeitwerk-2.6.14/lib/zeitwerk/loader/helpers.rb:25:in `ls'
	from .../vendor/bundle/ruby/3.3.0/gems/zeitwerk-2.6.14/lib/zeitwerk/loader/eager_load.rb:170:in `actual_eager_load_dir'
	from .../vendor/bundle/ruby/3.3.0/gems/zeitwerk-2.6.14/lib/zeitwerk/loader/eager_load.rb:17:in `block (2 levels) in eager_load'
	from .../vendor/bundle/ruby/3.3.0/gems/zeitwerk-2.6.14/lib/zeitwerk/loader/eager_load.rb:16:in `each'
	from .../vendor/bundle/ruby/3.3.0/gems/zeitwerk-2.6.14/lib/zeitwerk/loader/eager_load.rb:16:in `block in eager_load'
	from .../vendor/bundle/ruby/3.3.0/gems/zeitwerk-2.6.14/lib/zeitwerk/loader/eager_load.rb:10:in `synchronize'
	from .../vendor/bundle/ruby/3.3.0/gems/zeitwerk-2.6.14/lib/zeitwerk/loader/eager_load.rb:10:in `eager_load'
	from .../vendor/bundle/ruby/3.3.0/gems/zeitwerk-2.6.14/lib/zeitwerk/loader.rb:413:in `block in eager_load_all'
	from .../vendor/bundle/ruby/3.3.0/gems/zeitwerk-2.6.14/lib/zeitwerk/loader.rb:411:in `each'
	from .../vendor/bundle/ruby/3.3.0/gems/zeitwerk-2.6.14/lib/zeitwerk/loader.rb:411:in `eager_load_all'
	from .../vendor/bundle/ruby/3.3.0/gems/railties-7.1.3.4/lib/rails/application/finisher.rb:80:in `block in <module:Finisher>'
	from .../vendor/bundle/ruby/3.3.0/gems/railties-7.1.3.4/lib/rails/initializable.rb:32:in `instance_exec'
	from .../vendor/bundle/ruby/3.3.0/gems/railties-7.1.3.4/lib/rails/initializable.rb:32:in `run'
	from .../vendor/bundle/ruby/3.3.0/gems/railties-7.1.3.4/lib/rails/initializable.rb:61:in `block in run_initializers'
	from /home/jon/.rubies/ruby-3.3.2/lib/ruby/3.3.0/tsort.rb:231:in `block in tsort_each'
	from /home/jon/.rubies/ruby-3.3.2/lib/ruby/3.3.0/tsort.rb:353:in `block (2 levels) in each_strongly_connected_component'
	from /home/jon/.rubies/ruby-3.3.2/lib/ruby/3.3.0/tsort.rb:434:in `each_strongly_connected_component_from'
	from /home/jon/.rubies/ruby-3.3.2/lib/ruby/3.3.0/tsort.rb:352:in `block in each_strongly_connected_component'
	from /home/jon/.rubies/ruby-3.3.2/lib/ruby/3.3.0/tsort.rb:350:in `each'
	from /home/jon/.rubies/ruby-3.3.2/lib/ruby/3.3.0/tsort.rb:350:in `call'
	from /home/jon/.rubies/ruby-3.3.2/lib/ruby/3.3.0/tsort.rb:350:in `each_strongly_connected_component'
	from /home/jon/.rubies/ruby-3.3.2/lib/ruby/3.3.0/tsort.rb:229:in `tsort_each'
	from /home/jon/.rubies/ruby-3.3.2/lib/ruby/3.3.0/tsort.rb:208:in `tsort_each'
	from .../vendor/bundle/ruby/3.3.0/gems/railties-7.1.3.4/lib/rails/initializable.rb:60:in `run_initializers'
	from .../vendor/bundle/ruby/3.3.0/gems/railties-7.1.3.4/lib/rails/application.rb:426:in `initialize!'
	from .../config/environment.rb:7:in `<top (required)>'
	from /home/jon/.rubies/ruby-3.3.2/lib/ruby/3.3.0/bundled_gems.rb:74:in `require'
	from /home/jon/.rubies/ruby-3.3.2/lib/ruby/3.3.0/bundled_gems.rb:74:in `block (2 levels) in replace_require'
	from .../vendor/bundle/ruby/3.3.0/gems/zeitwerk-2.6.14/lib/zeitwerk/kernel.rb:34:in `require'
	from .../vendor/bundle/ruby/3.3.0/gems/railties-7.1.3.4/lib/rails/application.rb:402:in `require_environment!'
	from .../vendor/bundle/ruby/3.3.0/gems/railties-7.1.3.4/lib/rails/command/actions.rb:20:in `boot_application!'
	from .../vendor/bundle/ruby/3.3.0/gems/railties-7.1.3.4/lib/rails/commands/console/console_command.rb:105:in `perform'
	from .../vendor/bundle/ruby/3.3.0/gems/thor-1.3.1/lib/thor/command.rb:28:in `run'
	from .../vendor/bundle/ruby/3.3.0/gems/thor-1.3.1/lib/thor/invocation.rb:127:in `invoke_command'
	from .../vendor/bundle/ruby/3.3.0/gems/railties-7.1.3.4/lib/rails/command/base.rb:178:in `invoke_command'
	from .../vendor/bundle/ruby/3.3.0/gems/thor-1.3.1/lib/thor.rb:527:in `dispatch'
	from .../vendor/bundle/ruby/3.3.0/gems/railties-7.1.3.4/lib/rails/command/base.rb:73:in `perform'
	from .../vendor/bundle/ruby/3.3.0/gems/railties-7.1.3.4/lib/rails/command.rb:71:in `block in invoke'
	from .../vendor/bundle/ruby/3.3.0/gems/railties-7.1.3.4/lib/rails/command.rb:149:in `with_argv'
	from .../vendor/bundle/ruby/3.3.0/gems/railties-7.1.3.4/lib/rails/command.rb:69:in `invoke'
	from .../vendor/bundle/ruby/3.3.0/gems/railties-7.1.3.4/lib/rails/commands.rb:18:in `<top (required)>'
	from /home/jon/.rubies/ruby-3.3.2/lib/ruby/3.3.0/bundled_gems.rb:74:in `require'
	from /home/jon/.rubies/ruby-3.3.2/lib/ruby/3.3.0/bundled_gems.rb:74:in `block (2 levels) in replace_require'
	from bin/rails:4:in `<main>'

As a workaround, my application requires ActionCable, but it doesn't actually use it.

Removing the eager loading, does not remove using Turbo in the frontend. There is no change there.

Some projects use RailsAdmin without using Turbo or ActionCable. In
these applications, when the Rails configuration option
`config.eager_load` is set to true, the RailsAdmin requirement of turbo
will result in eager loading files that can't load.

The result is the following error:

```
.../vendor/bundle/ruby/3.3.0/gems/turbo-rails-2.0.5/app/channels/turbo/streams_channel.rb:34:in `<top (required)>': uninitialized constant ActionCable (NameError)

class Turbo::StreamsChannel < ActionCable::Channel::Base
                              ^^^^^^^^^^^
Did you mean?  ActionMailer
	from /home/jon/.rubies/ruby-3.3.2/lib/ruby/3.3.0/bundled_gems.rb:74:in `require'
	from /home/jon/.rubies/ruby-3.3.2/lib/ruby/3.3.0/bundled_gems.rb:74:in `block (2 levels) in replace_require'
	from .../vendor/bundle/ruby/3.3.0/gems/zeitwerk-2.6.14/lib/zeitwerk/kernel.rb:26:in `require'
	from .../vendor/bundle/ruby/3.3.0/gems/zeitwerk-2.6.14/lib/zeitwerk/loader/helpers.rb:139:in `const_get'
	from .../vendor/bundle/ruby/3.3.0/gems/zeitwerk-2.6.14/lib/zeitwerk/loader/helpers.rb:139:in `cget'
	from .../vendor/bundle/ruby/3.3.0/gems/zeitwerk-2.6.14/lib/zeitwerk/loader/eager_load.rb:175:in `block in actual_eager_load_dir'
	from .../vendor/bundle/ruby/3.3.0/gems/zeitwerk-2.6.14/lib/zeitwerk/loader/helpers.rb:42:in `block in ls'
	from .../vendor/bundle/ruby/3.3.0/gems/zeitwerk-2.6.14/lib/zeitwerk/loader/helpers.rb:25:in `each'
	from .../vendor/bundle/ruby/3.3.0/gems/zeitwerk-2.6.14/lib/zeitwerk/loader/helpers.rb:25:in `ls'
	from .../vendor/bundle/ruby/3.3.0/gems/zeitwerk-2.6.14/lib/zeitwerk/loader/eager_load.rb:170:in `actual_eager_load_dir'
	from .../vendor/bundle/ruby/3.3.0/gems/zeitwerk-2.6.14/lib/zeitwerk/loader/eager_load.rb:17:in `block (2 levels) in eager_load'
	from .../vendor/bundle/ruby/3.3.0/gems/zeitwerk-2.6.14/lib/zeitwerk/loader/eager_load.rb:16:in `each'
	from .../vendor/bundle/ruby/3.3.0/gems/zeitwerk-2.6.14/lib/zeitwerk/loader/eager_load.rb:16:in `block in eager_load'
	from .../vendor/bundle/ruby/3.3.0/gems/zeitwerk-2.6.14/lib/zeitwerk/loader/eager_load.rb:10:in `synchronize'
	from .../vendor/bundle/ruby/3.3.0/gems/zeitwerk-2.6.14/lib/zeitwerk/loader/eager_load.rb:10:in `eager_load'
	from .../vendor/bundle/ruby/3.3.0/gems/zeitwerk-2.6.14/lib/zeitwerk/loader.rb:413:in `block in eager_load_all'
	from .../vendor/bundle/ruby/3.3.0/gems/zeitwerk-2.6.14/lib/zeitwerk/loader.rb:411:in `each'
	from .../vendor/bundle/ruby/3.3.0/gems/zeitwerk-2.6.14/lib/zeitwerk/loader.rb:411:in `eager_load_all'
	from .../vendor/bundle/ruby/3.3.0/gems/railties-7.1.3.4/lib/rails/application/finisher.rb:80:in `block in <module:Finisher>'
	from .../vendor/bundle/ruby/3.3.0/gems/railties-7.1.3.4/lib/rails/initializable.rb:32:in `instance_exec'
	from .../vendor/bundle/ruby/3.3.0/gems/railties-7.1.3.4/lib/rails/initializable.rb:32:in `run'
	from .../vendor/bundle/ruby/3.3.0/gems/railties-7.1.3.4/lib/rails/initializable.rb:61:in `block in run_initializers'
	from /home/jon/.rubies/ruby-3.3.2/lib/ruby/3.3.0/tsort.rb:231:in `block in tsort_each'
	from /home/jon/.rubies/ruby-3.3.2/lib/ruby/3.3.0/tsort.rb:353:in `block (2 levels) in each_strongly_connected_component'
	from /home/jon/.rubies/ruby-3.3.2/lib/ruby/3.3.0/tsort.rb:434:in `each_strongly_connected_component_from'
	from /home/jon/.rubies/ruby-3.3.2/lib/ruby/3.3.0/tsort.rb:352:in `block in each_strongly_connected_component'
	from /home/jon/.rubies/ruby-3.3.2/lib/ruby/3.3.0/tsort.rb:350:in `each'
	from /home/jon/.rubies/ruby-3.3.2/lib/ruby/3.3.0/tsort.rb:350:in `call'
	from /home/jon/.rubies/ruby-3.3.2/lib/ruby/3.3.0/tsort.rb:350:in `each_strongly_connected_component'
	from /home/jon/.rubies/ruby-3.3.2/lib/ruby/3.3.0/tsort.rb:229:in `tsort_each'
	from /home/jon/.rubies/ruby-3.3.2/lib/ruby/3.3.0/tsort.rb:208:in `tsort_each'
	from .../vendor/bundle/ruby/3.3.0/gems/railties-7.1.3.4/lib/rails/initializable.rb:60:in `run_initializers'
	from .../vendor/bundle/ruby/3.3.0/gems/railties-7.1.3.4/lib/rails/application.rb:426:in `initialize!'
	from .../config/environment.rb:7:in `<top (required)>'
	from /home/jon/.rubies/ruby-3.3.2/lib/ruby/3.3.0/bundled_gems.rb:74:in `require'
	from /home/jon/.rubies/ruby-3.3.2/lib/ruby/3.3.0/bundled_gems.rb:74:in `block (2 levels) in replace_require'
	from .../vendor/bundle/ruby/3.3.0/gems/zeitwerk-2.6.14/lib/zeitwerk/kernel.rb:34:in `require'
	from .../vendor/bundle/ruby/3.3.0/gems/railties-7.1.3.4/lib/rails/application.rb:402:in `require_environment!'
	from .../vendor/bundle/ruby/3.3.0/gems/railties-7.1.3.4/lib/rails/command/actions.rb:20:in `boot_application!'
	from .../vendor/bundle/ruby/3.3.0/gems/railties-7.1.3.4/lib/rails/commands/console/console_command.rb:105:in `perform'
	from .../vendor/bundle/ruby/3.3.0/gems/thor-1.3.1/lib/thor/command.rb:28:in `run'
	from .../vendor/bundle/ruby/3.3.0/gems/thor-1.3.1/lib/thor/invocation.rb:127:in `invoke_command'
	from .../vendor/bundle/ruby/3.3.0/gems/railties-7.1.3.4/lib/rails/command/base.rb:178:in `invoke_command'
	from .../vendor/bundle/ruby/3.3.0/gems/thor-1.3.1/lib/thor.rb:527:in `dispatch'
	from .../vendor/bundle/ruby/3.3.0/gems/railties-7.1.3.4/lib/rails/command/base.rb:73:in `perform'
	from .../vendor/bundle/ruby/3.3.0/gems/railties-7.1.3.4/lib/rails/command.rb:71:in `block in invoke'
	from .../vendor/bundle/ruby/3.3.0/gems/railties-7.1.3.4/lib/rails/command.rb:149:in `with_argv'
	from .../vendor/bundle/ruby/3.3.0/gems/railties-7.1.3.4/lib/rails/command.rb:69:in `invoke'
	from .../vendor/bundle/ruby/3.3.0/gems/railties-7.1.3.4/lib/rails/commands.rb:18:in `<top (required)>'
	from /home/jon/.rubies/ruby-3.3.2/lib/ruby/3.3.0/bundled_gems.rb:74:in `require'
	from /home/jon/.rubies/ruby-3.3.2/lib/ruby/3.3.0/bundled_gems.rb:74:in `block (2 levels) in replace_require'
	from bin/rails:4:in `<main>'
```

As a workaround, my application requires ActionCable, but it doesn't
actually use it.

Removing the eager loading, does not remove using Turbo in the frontend.
There is no change there.
@coveralls
Copy link

Coverage Status

coverage: 95.97% (+0.02%) from 95.947%
when pulling 0c2cdb3 on jdufresne:eager-turbo
into 91737ab on railsadminteam:master.

@mshibuya
Copy link
Member

This was already addressed in turbo-rails.
hotwired/turbo-rails#512
Please wait for the next release of it, or use the github source:

gem 'turbo-rails', github: 'hotwired/turbo-rails'

@mshibuya mshibuya closed this Jun 15, 2024
@jdufresne
Copy link
Member Author

Thanks for that link! Will do.

Can you explain why the require 'turbo-rails' exists in Rails Admin if it is only used in JavaScript? What is that for? As we see here, removing it doesn't cause a test to fail, so maybe we would benefit from a new test to demonstrate.

@mshibuya
Copy link
Member

It's necessary for asset pipeline configuration. Without it assets:precompile fails.

% rails assets:precompile
bin/rails aborted!
Sprockets::FileNotFound: couldn't find file 'turbo' with type 'application/javascript' (Sprockets::FileNotFound)
...

@jdufresne jdufresne deleted the eager-turbo branch October 8, 2024 22:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants