spring
spring copied to clipboard
Support dual/multi-booting Rails apps with different Gemfiles
Out-of-the box, spring needs custom configuration of the SPRING_APPLICATION_ID env var to support dual-booting different Gemfiles. This is because the generated application_id only takes into account the RUBY_VERSION and the project_root path.
Would it be a welcome PR to change the current application_id generation to use the Gemfile lockfile path instead of the project_root path? This would allow Spring to support multiple gemfiles without custom config, as it will start a spring server for each Gemfile:
def application_id
- ENV["SPRING_APPLICATION_ID"] || Digest::MD5.hexdigest(RUBY_VERSION + project_root.to_s)
+ ENV["SPRING_APPLICATION_ID"] || Digest::MD5.hexdigest(RUBY_VERSION + Bundler.default_lockfile.to_s)
end
For developers wanting to support this today, you can set SPRING_APPLICATION_ID in bin/spring by adding the lines shown below.
File: bin/spring
#!/usr/bin/env ruby
# This file loads Spring without using Bundler, in order to be fast.
# It gets overwritten when you run the `spring binstub` command.
unless defined?(Spring)
require 'rubygems'
require 'bundler'
+ # The default application_id generated by Spring::Env#application_id
+ # does not support booting with different Gemfiles. The default
+ # value is `Digest::MD5.hexdigest(RUBY_VERSION + project_root.to_s)`
+ # Here, we set the SPRING_APPLICATION_ID env var to customize the
+ # application_id so it takes the current gemfile into account, to
+ # support booting with different Gemfiles.
+ def configure_spring_for_multiple_gemfiles
+ require 'digest/md5'
+ ENV["SPRING_APPLICATION_ID"] = Digest::MD5.hexdigest(RUBY_VERSION + Bundler.default_lockfile.to_s)
+ end
+ configure_spring_for_multiple_gemfiles
+
lockfile = Bundler::LockfileParser.new(Bundler.default_lockfile.read)
spring = lockfile.specs.detect { |spec| spec.name == 'spring' }
if spring
Gem.use_paths Gem.dir, Bundler.bundle_path.to_s, *Gem.path
gem 'spring', spring.version
require 'spring/binstub'
end
end
To check this is working, perform the following steps:
- Kill all current spring servers: Running
bin/spring stopandpkill -9 springshould do it. - Run a rails console using the default
Gemfile:bin/rails c. Check theRails.versionis as expected forGemfile. - Run another rails console, using a non-default
Gemfile:BUNDLE_GEMFILE=Gemfile_next bin/rails c. Check theRails.versionis as expected forGemfile. - Run
bin/spring status. This should show a spring development env running. Note the process ids. - Run
BUNDLE_GEMFILE=Gemfile_next bin/spring status. This should show another spring development env running, but the process ids should be different to those noted in the previous step.
To ensure the above config isn't accidentally deleted from bin/spring (say when the binstub is regenerated), in config/spring.rb add the following:
Spring.after_fork do
require 'digest/md5'
expected_spring_application_id = Digest::MD5.hexdigest(RUBY_VERSION + Bundler.default_lockfile.to_s)
if ENV["SPRING_APPLICATION_ID"] != expected_spring_application_id
raise "Spring is misconfigured! Check bin/spring defines and calls `configure_spring_for_multiple_gemfiles`"
end
end