rails / spring

Rails application preloader
MIT License
2.8k stars 339 forks source link

Spring binstub error when requiring class from lib/ in application.rb #642

Open olivierlacan opened 3 years ago

olivierlacan commented 3 years ago

Given a file in lib/ named thing.rb which required within application.rb like this:

require_relative "boot"

require "rails/all"

# Require the gems listed in Gemfile, including any gems
# you've limited to :test, :development, or :production.
Bundler.require(*Rails.groups)

require "thing"

module Rails611LibRequireSpringBug
  class Application < Rails::Application
    # Initialize configuration defaults for originally generated Rails version.
    config.load_defaults 6.1

    # Configuration for the application, engines, and railties goes here.
    #
    # These settings can be overridden in specific environments using the files
    # in config/environments, which are processed later.
    #
    # config.time_zone = "Central Time (US & Canada)"
    # config.eager_load_paths << Rails.root.join("lib")

    # NOTE: my intent was to use the following code below:
    # config.middleware.use Thing
  end
end

When rails server is launched, I was surprised to see this Spring-related error. I doubt it's truly related to Spring, but I felt like I should at least document this behavior since it may be surprising to some people.

$ rails s
You've tried to invoke Spring when it's already loaded (i.e. the Spring constant is defined).

This is probably because you generated binstubs with Spring 1.0, and you now have a Spring version > 1.0 on your system. To solve this, upgrade your bundle to the latest Spring version and then run `bundle exec spring binstub --all` to regenerate your binstubs. This is a one-time step necessary to upgrade from 1.0 to 1.1.

Here's the backtrace:

/Users/olivierlacan/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/bootsnap-1.7.0/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:59:in `load'
/Users/olivierlacan/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/bootsnap-1.7.0/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:59:in `load'
/Users/olivierlacan/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/activesupport-6.1.1/lib/active_support/dependencies.rb:326:in `block in load'
/Users/olivierlacan/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/activesupport-6.1.1/lib/active_support/dependencies.rb:299:in `load_dependency'
/Users/olivierlacan/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/activesupport-6.1.1/lib/active_support/dependencies.rb:326:in `load'
/Users/olivierlacan/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/spring-2.1.1/lib/spring/binstub.rb:11:in `<main>'
/Users/olivierlacan/.rbenv/versions/2.7.2/lib/ruby/2.7.0/rubygems/core_ext/kernel_require.rb:92:in `require'
/Users/olivierlacan/.rbenv/versions/2.7.2/lib/ruby/2.7.0/rubygems/core_ext/kernel_require.rb:92:in `require'
/Users/olivierlacan/dev/sandbox/rails-6-1-1-lib-require-spring-bug/bin/spring:10:in `block in <top (required)>'
/Users/olivierlacan/dev/sandbox/rails-6-1-1-lib-require-spring-bug/bin/spring:7:in `tap'
/Users/olivierlacan/dev/sandbox/rails-6-1-1-lib-require-spring-bug/bin/spring:7:in `<top (required)>'
bin/rails:2:in `load'
bin/rails:2:in `<main>'

The only way I avoid it is by moving the require call within the Application class definition, which I had to do in the case where Thing is a Rack middleware I wanted to insert. Although I don't have huge qualms about having to do so, I don't remember specific instructions from the Rails Guides warning against requiring (non reloadable) code outside of the Application class definition. But I'll admit I might just be tired.

Here's a reproduction app: https://github.com/olivierlacan/rails-6-1-1-lib-require-spring-bug

I did initially follow the instructions to bundle exec spring binstub --all but I doubt this issue has anything to do with the Spring version since this is a brand new app whose binstubs are Spring 2.1.1 native.

Considering the Stacktrace, this feels more likely to be a Bootsnap bug so I'll gladly move this issue over to that repo if that makes more sense.

deivid-rodriguez commented 3 years ago

I tried to repro this, but I couldn't. I get this:

$ rails s
Traceback (most recent call last):
    45: from bin/rails:2:in `<main>'
    44: from bin/rails:2:in `load'
    43: from /home/deivid/Code/playground/rails-6-1-1-lib-require-spring-bug/bin/spring:7:in `<top (required)>'
    42: from /home/deivid/Code/playground/rails-6-1-1-lib-require-spring-bug/bin/spring:7:in `tap'
    41: from /home/deivid/Code/playground/rails-6-1-1-lib-require-spring-bug/bin/spring:10:in `block in <top (required)>'
    40: from /home/deivid/.rbenv/versions/2.7.2/lib/ruby/site_ruby/2.7.0/rubygems/core_ext/kernel_require.rb:85:in `require'
    39: from /home/deivid/.rbenv/versions/2.7.2/lib/ruby/site_ruby/2.7.0/rubygems/core_ext/kernel_require.rb:85:in `require'
    38: from /home/deivid/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/spring-2.1.1/lib/spring/binstub.rb:11:in `<top (required)>'
    37: from /home/deivid/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/spring-2.1.1/lib/spring/binstub.rb:11:in `load'
    36: from /home/deivid/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/spring-2.1.1/bin/spring:49:in `<top (required)>'
    35: from /home/deivid/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/spring-2.1.1/lib/spring/client.rb:30:in `run'
    34: from /home/deivid/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/spring-2.1.1/lib/spring/client/command.rb:7:in `call'
    33: from /home/deivid/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/spring-2.1.1/lib/spring/client/rails.rb:28:in `call'
    32: from /home/deivid/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/spring-2.1.1/lib/spring/client/rails.rb:28:in `load'
    31: from /home/deivid/Code/playground/rails-6-1-1-lib-require-spring-bug/bin/rails:5:in `<top (required)>'
    30: from /home/deivid/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/bootsnap-1.7.0/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:31:in `require'
    29: from /home/deivid/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/bootsnap-1.7.0/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:22:in `require_with_bootsnap_lfi'
    28: from /home/deivid/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/bootsnap-1.7.0/lib/bootsnap/load_path_cache/loaded_features_index.rb:92:in `register'
    27: from /home/deivid/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/bootsnap-1.7.0/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:23:in `block in require_with_bootsnap_lfi'
    26: from /home/deivid/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/bootsnap-1.7.0/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:23:in `require'
    25: from /home/deivid/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/railties-6.1.1/lib/rails/commands.rb:18:in `<main>'
    24: from /home/deivid/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/railties-6.1.1/lib/rails/command.rb:50:in `invoke'
    23: from /home/deivid/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/railties-6.1.1/lib/rails/command/base.rb:69:in `perform'
    22: from /home/deivid/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/thor-1.1.0/lib/thor.rb:392:in `dispatch'
    21: from /home/deivid/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/thor-1.1.0/lib/thor/invocation.rb:127:in `invoke_command'
    20: from /home/deivid/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/thor-1.1.0/lib/thor/command.rb:27:in `run'
    19: from /home/deivid/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/railties-6.1.1/lib/rails/commands/server/server_command.rb:135:in `perform'
    18: from /home/deivid/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/railties-6.1.1/lib/rails/commands/server/server_command.rb:135:in `tap'
    17: from /home/deivid/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/railties-6.1.1/lib/rails/commands/server/server_command.rb:138:in `block in perform'
    16: from /home/deivid/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/activesupport-6.1.1/lib/active_support/dependencies.rb:332:in `require'
    15: from /home/deivid/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/activesupport-6.1.1/lib/active_support/dependencies.rb:299:in `load_dependency'
    14: from /home/deivid/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/activesupport-6.1.1/lib/active_support/dependencies.rb:332:in `block in require'
    13: from /home/deivid/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/bootsnap-1.7.0/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:31:in `require'
    12: from /home/deivid/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/bootsnap-1.7.0/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:22:in `require_with_bootsnap_lfi'
    11: from /home/deivid/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/bootsnap-1.7.0/lib/bootsnap/load_path_cache/loaded_features_index.rb:92:in `register'
    10: from /home/deivid/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/bootsnap-1.7.0/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:23:in `block in require_with_bootsnap_lfi'
     9: from /home/deivid/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/bootsnap-1.7.0/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:23:in `require'
     8: from /home/deivid/Code/playground/rails-6-1-1-lib-require-spring-bug/config/application.rb:9:in `<main>'
     7: from /home/deivid/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/activesupport-6.1.1/lib/active_support/dependencies.rb:332:in `require'
     6: from /home/deivid/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/activesupport-6.1.1/lib/active_support/dependencies.rb:299:in `load_dependency'
     5: from /home/deivid/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/activesupport-6.1.1/lib/active_support/dependencies.rb:332:in `block in require'
     4: from /home/deivid/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/bootsnap-1.7.0/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:44:in `require'
     3: from /home/deivid/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/bootsnap-1.7.0/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:22:in `require_with_bootsnap_lfi'
     2: from /home/deivid/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/bootsnap-1.7.0/lib/bootsnap/load_path_cache/loaded_features_index.rb:89:in `register'
     1: from /home/deivid/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/bootsnap-1.7.0/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:23:in `block in require_with_bootsnap_lfi'
/home/deivid/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/bootsnap-1.7.0/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:23:in `require': cannot load such file -- thing (LoadError)

If I manually add lib to the LOAD_PATH using RUBYOPT=-Ilib rails s, then the app boots fine.

JuPlutonic commented 3 years ago

So @olivierlacan, close it please.