Skip to content

Commit f3ce221

Browse files
committed
Make Suspenders fail if running with an unsupported Rails version
This work is part of the Rescue project: https://github.com/thoughtbot/suspenders/projects/1 ** Problem In a scenario where the following Rails versions are installed: - 6.0.4.7 - 6.1.4.1 The `bin/suspenders` command will pick up the most recent version, 6.1.4.1. Now that Rails has surpassed the 6.0 series, it is very common to have more than one version installed alongside the version installed by Suspenders. A failure on the Suspenders command due to a mismatching Rails version is confusing and violates the principle of least surprise, and may also drive users away. The only way to overcome this bug with the current `bin/suspenders` command is to be explicit about the Rails version: ```sh suspenders _6.0.4.1_ my-app ``` Unfortunately, this is an obscure and undocumented feature, and we can't expect users to know about it. Note that Suspenders currently works with Rails `~> 6.0.0` and is not compatible with Rails 6.1. ** Solution The solution is to read the Rails version from Bundler and then activate its gem bin path. We can't `Bunder.require(:default)` because a polluted bundler / gem environment may interfere with the functionality of generators in unexpected ways, given that subprocesses inherit the environment of parents -- therefore, the cleaner our environment the better. As part of the "fail early" mindset, we're also failing if an explicit Rails version that can't be found is specified. ** Steps to reproduce (using asdf) ```sh asdf install ruby 2.7.4 git clone [email protected]:thoughtbot/suspenders cd suspenders bundle install gem install rails -v 6.1.4.1 bin/suspenders my-app ``` Last error line: ``` 1: from /home/user/suspenders/lib/suspenders/app_builder.rb:101 :in `setup_asset_host' /home/user/suspenders/lib/suspenders/actions.rb:7:in `replace_in_file': "# config.action_controller.asset_host = 'http://assets.example.com'" not found in config/environments/production.rb (RuntimeError) ``` We are getting this error because in Rails 6.1 the commented line that `replace_in_file` is looking for is now: ```ruby \# config.asset_host = 'http://assets.example.com' ```
1 parent 232a2cc commit f3ce221

File tree

1 file changed

+20
-6
lines changed

1 file changed

+20
-6
lines changed

bin/suspenders

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,12 @@ require 'pathname'
44
source_path = (Pathname.new(__FILE__).dirname + '../lib').expand_path
55
$LOAD_PATH << source_path
66

7+
activate_rails_version = ->(rails_version) do
8+
rails_bin_path = Gem.activate_bin_path("railties", "rails", rails_version)
9+
rails_path = File.expand_path("../..", rails_bin_path)
10+
$LOAD_PATH.unshift(rails_path)
11+
end
12+
713
if str = ARGV.first
814
str = str.b[/\A_(.*)_\z/, 1]
915

@@ -12,23 +18,31 @@ if str = ARGV.first
1218
ARGV.shift
1319

1420
begin
15-
rails_bin_path = Gem.activate_bin_path("railties", "rails", rails_version)
16-
rails_path = File.expand_path("../..", rails_bin_path)
17-
$LOAD_PATH.unshift(rails_path)
21+
activate_rails_version.call(rails_version)
1822
rescue Gem::GemNotFoundException
19-
$stderr.puts "#{rails_version} requested but no Rails is installed yet. Hoping for the best with the default."
23+
abort "Suspenders error: Unable to find Rails version #{rails_version}"
24+
end
25+
else
26+
require "bundler"
27+
28+
spec = Bundler.definition.specs.find { |s| s.name == "rails" }
29+
30+
if spec.nil?
31+
abort "Suspenders error: Unable to find Rails in Bundle"
2032
end
33+
34+
activate_rails_version.call(spec.version.to_s)
2135
end
2236
end
2337

24-
require 'suspenders'
38+
require "suspenders"
2539

2640
if ARGV.empty?
2741
puts "Please provide a path for the new application"
2842
puts
2943
puts "See --help for more info"
3044
exit 0
31-
elsif ['-v', '--version'].include? ARGV[0]
45+
elsif ["-v", "--version"].include? ARGV[0]
3246
puts Suspenders::VERSION
3347
exit 0
3448
end

0 commit comments

Comments
 (0)