Skip to content

Commit 13181a7

Browse files
JuanVqzarielj
andauthored
Move bundle_report rails compatibility logic into a class (#137)
* Move bundle_report rails compatibility logic into a class I extracted it into a class because I think it will be easier to use the `incompatible_gems_by_state` data there. Based on the code review * Add incompatible with new compatible versions * Update changelog * Capture stdout to assert Co-authored-by: Ariel <[email protected]> --------- Co-authored-by: Ariel <[email protected]>
1 parent aca1c12 commit 13181a7

File tree

9 files changed

+159
-67
lines changed

9 files changed

+159
-67
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# main [(unreleased)](https://github.com/fastruby/next_rails/compare/v1.4.4...main)
22

33
- [BUGFIX: example](https://github.com/fastruby/next_rails/pull/<number>)
4+
- [Move rails_version compatibility to its own class](https://github.com/fastruby/next_rails/pull/137)
45

56
* Your changes/patches go here.
67

exe/bundle_report

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,9 +67,9 @@ at_exit do
6767
when "outdated" then NextRails::BundleReport.outdated(options.fetch(:format, nil))
6868
else
6969
if options[:ruby_version]
70-
NextRails::BundleReport.compatibility(ruby_version: options.fetch(:ruby_version, "2.3"))
70+
NextRails::BundleReport.ruby_compatibility(ruby_version: options.fetch(:ruby_version, "2.3"))
7171
else
72-
NextRails::BundleReport.compatibility(rails_version: options.fetch(:rails_version, "5.0"), include_rails_gems: options.fetch(:include_rails_gems, false))
72+
NextRails::BundleReport.rails_compatibility(rails_version: options.fetch(:rails_version, "5.0"), include_rails_gems: options.fetch(:include_rails_gems, false))
7373
end
7474
end
7575
end

lib/next_rails.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
require "next_rails/init"
66
require "next_rails/bundle_report"
77
require "next_rails/bundle_report/ruby_version_compatibility"
8+
require "next_rails/bundle_report/rails_version_compatibility"
89
require "deprecation_tracker"
910

1011
module NextRails

lib/next_rails/bundle_report.rb

Lines changed: 8 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -8,69 +8,18 @@ module NextRails
88
module BundleReport
99
extend self
1010

11-
def compatibility(rails_version: nil, ruby_version: nil, include_rails_gems: nil)
12-
return puts RubyVersionCompatibility.new(options: { ruby_version: ruby_version }).generate if ruby_version
11+
def ruby_compatibility(ruby_version: nil)
12+
return unless ruby_version
1313

14-
incompatible_gems = NextRails::GemInfo.all.reject do |gem|
15-
gem.compatible_with_rails?(rails_version: rails_version) || (!include_rails_gems && gem.from_rails?)
16-
end.sort_by { |gem| gem.name }
17-
18-
incompatible_gems.each { |gem| gem.find_latest_compatible(rails_version: rails_version) }
19-
20-
incompatible_gems_by_state = incompatible_gems.group_by { |gem| gem.state(rails_version) }
21-
22-
puts erb_output(incompatible_gems_by_state, incompatible_gems, rails_version)
14+
options = { ruby_version: ruby_version }
15+
puts RubyVersionCompatibility.new(options: options).generate
2316
end
2417

25-
def erb_output(incompatible_gems_by_state, incompatible_gems, rails_version)
26-
template = <<-ERB
27-
<% if incompatible_gems_by_state[:found_compatible] -%>
28-
<%= Rainbow("=> Incompatible with Rails #{rails_version} (with new versions that are compatible):").white.bold %>
29-
<%= Rainbow("These gems will need to be upgraded before upgrading to Rails #{rails_version}.").italic %>
30-
31-
<% incompatible_gems_by_state[:found_compatible].each do |gem| -%>
32-
<%= gem_header(gem) %> - upgrade to <%= gem.latest_compatible_version.version %>
33-
<% end -%>
34-
35-
<% end -%>
36-
<% if incompatible_gems_by_state[:incompatible] -%>
37-
<%= Rainbow("=> Incompatible with Rails #{rails_version} (with no new compatible versions):").white.bold %>
38-
<%= Rainbow("These gems will need to be removed or replaced before upgrading to Rails #{rails_version}.").italic %>
39-
40-
<% incompatible_gems_by_state[:incompatible].each do |gem| -%>
41-
<%= gem_header(gem) %> - new version, <%= gem.latest_version.version %>, is not compatible with Rails #{rails_version}
42-
<% end -%>
43-
44-
<% end -%>
45-
<% if incompatible_gems_by_state[:no_new_version] -%>
46-
<%= Rainbow("=> Incompatible with Rails #{rails_version} (with no new versions):").white.bold %>
47-
<%= Rainbow("These gems will need to be upgraded by us or removed before upgrading to Rails #{rails_version}.").italic %>
48-
<%= Rainbow("This list is likely to contain internal gems, like Cuddlefish.").italic %>
49-
50-
<% incompatible_gems_by_state[:no_new_version].each do |gem| -%>
51-
<%= gem_header(gem) %> - new version not found
52-
<% end -%>
53-
54-
<% end -%>
55-
<%= Rainbow(incompatible_gems.length.to_s).red %> gems incompatible with Rails <%= rails_version %>
56-
ERB
57-
58-
erb_version = ERB.version
59-
if erb_version =~ /erb.rb \[([\d\.]+) .*\]/
60-
erb_version = $1
61-
end
62-
63-
if Gem::Version.new(erb_version) < Gem::Version.new("2.2")
64-
ERB.new(template, nil, "-").result(binding)
65-
else
66-
ERB.new(template, trim_mode: "-").result(binding)
67-
end
68-
end
18+
def rails_compatibility(rails_version: nil, include_rails_gems: nil)
19+
return unless rails_version
6920

70-
def gem_header(_gem)
71-
header = Rainbow("#{_gem.name} #{_gem.version}").bold
72-
header << Rainbow(" (loaded from git)").magenta if _gem.sourced_from_git?
73-
header
21+
options = { rails_version: rails_version, include_rails_gems: include_rails_gems }
22+
puts RailsVersionCompatibility.new(options: options).generate
7423
end
7524

7625
def compatible_ruby_version(rails_version)
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
class NextRails::BundleReport::RailsVersionCompatibility
2+
def initialize(gems: NextRails::GemInfo.all, options: {})
3+
@gems = gems
4+
@options = options
5+
end
6+
7+
def generate
8+
erb_output
9+
end
10+
11+
def incompatible_gems_by_state
12+
@incompatible_gems_by_state ||= begin
13+
incompatible_gems.each { |gem| gem.find_latest_compatible(rails_version: rails_version) }
14+
incompatible_gems.group_by { |gem| gem.state(rails_version) }
15+
end
16+
end
17+
18+
private
19+
20+
def erb_output
21+
template = <<-ERB
22+
<% if incompatible_gems_by_state[:found_compatible] -%>
23+
<%= Rainbow("=> Incompatible with Rails #{rails_version} (with new versions that are compatible):").white.bold %>
24+
<%= Rainbow("These gems will need to be upgraded before upgrading to Rails #{rails_version}.").italic %>
25+
26+
<% incompatible_gems_by_state[:found_compatible].each do |gem| -%>
27+
<%= gem_header(gem) %> - upgrade to <%= gem.latest_compatible_version.version %>
28+
<% end -%>
29+
30+
<% end -%>
31+
<% if incompatible_gems_by_state[:incompatible] -%>
32+
<%= Rainbow("=> Incompatible with Rails #{rails_version} (with no new compatible versions):").white.bold %>
33+
<%= Rainbow("These gems will need to be removed or replaced before upgrading to Rails #{rails_version}.").italic %>
34+
35+
<% incompatible_gems_by_state[:incompatible].each do |gem| -%>
36+
<%= gem_header(gem) %> - new version, <%= gem.latest_version.version %>, is not compatible with Rails #{rails_version}
37+
<% end -%>
38+
39+
<% end -%>
40+
<% if incompatible_gems_by_state[:no_new_version] -%>
41+
<%= Rainbow("=> Incompatible with Rails #{rails_version} (with no new versions):").white.bold %>
42+
<%= Rainbow("These gems will need to be upgraded by us or removed before upgrading to Rails #{rails_version}.").italic %>
43+
<%= Rainbow("This list is likely to contain internal gems, like Cuddlefish.").italic %>
44+
45+
<% incompatible_gems_by_state[:no_new_version].each do |gem| -%>
46+
<%= gem_header(gem) %> - new version not found
47+
<% end -%>
48+
49+
<% end -%>
50+
<%= Rainbow(incompatible_gems.length.to_s).red %> gems incompatible with Rails <%= rails_version %>
51+
ERB
52+
53+
erb_version = ERB.version
54+
if erb_version =~ /erb.rb \[([\d\.]+) .*\]/
55+
erb_version = $1
56+
end
57+
58+
if Gem::Version.new(erb_version) < Gem::Version.new("2.2")
59+
ERB.new(template, nil, "-").result(binding)
60+
else
61+
ERB.new(template, trim_mode: "-").result(binding)
62+
end
63+
end
64+
65+
def gem_header(_gem)
66+
header = Rainbow("#{_gem.name} #{_gem.version}").bold
67+
header << Rainbow(" (loaded from git)").magenta if _gem.sourced_from_git?
68+
header
69+
end
70+
71+
def incompatible_gems
72+
@incompatible_gems ||= @gems.reject do |gem|
73+
gem.compatible_with_rails?(rails_version: rails_version) || (!include_rails_gems && gem.from_rails?)
74+
end.sort_by { |gem| gem.name }
75+
end
76+
77+
def rails_version
78+
@options[:rails_version]
79+
end
80+
81+
def include_rails_gems
82+
@options[:include_rails_gems]
83+
end
84+
end
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# frozen_string_literal: true
2+
3+
require "spec_helper"
4+
5+
RSpec.describe NextRails::BundleReport::RailsVersionCompatibility do
6+
describe "#generate" do
7+
it "returns non incompatible gems" do
8+
output = NextRails::BundleReport::RailsVersionCompatibility.new(options: { rails_version: 7.0 }).generate
9+
expect(output).to match "gems incompatible with Rails 7.0"
10+
end
11+
12+
it "returns incompatible with compatible versions" do
13+
next_rails_version = 7.1
14+
specification = Gem::Specification.new do |s|
15+
s.name = "audited"
16+
s.version = "5.1.0"
17+
s.add_dependency "rails", ">= 5.0", "< 7.1"
18+
end
19+
audited = NextRails::GemInfo.new(specification)
20+
gems = [audited]
21+
22+
allow_any_instance_of(described_class).to receive(:incompatible_gems_by_state)
23+
.and_return({ found_compatible: gems })
24+
25+
allow(audited).to receive(:latest_compatible_version).and_return(Gem::Version.new("5.8.0"))
26+
27+
output =
28+
NextRails::BundleReport::RailsVersionCompatibility.new(
29+
gems: gems,
30+
options: { rails_version: next_rails_version, include_rails_gems: false }
31+
).generate
32+
33+
expect(output).to include("Incompatible with Rails 7.1 (with new versions that are compatible):")
34+
expect(output).to include("These gems will need to be upgraded before upgrading to Rails 7.1.")
35+
expect(output).to include("- upgrade to 5.8.0")
36+
expect(output).to include("gems incompatible with Rails 7.1")
37+
end
38+
end
39+
end
40+

spec/next_rails/bundle_report/ruby_version_compatibility_spec.rb

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
# frozen_string_literal: true
22

33
require "spec_helper"
4-
require "next_rails/bundle_report/ruby_version_compatibility"
54

65
RSpec.describe NextRails::BundleReport::RubyVersionCompatibility do
76
let(:ruby_3_0_gem) do

spec/next_rails/bundle_report_spec.rb

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -64,12 +64,21 @@
6464
end
6565
end
6666

67-
describe ".compatibility" do
68-
describe "output" do
69-
it "returns ERB generated output" do
70-
output = NextRails::BundleReport.erb_output({}, [], 7.0)
71-
expect(output).to match "gems incompatible with Rails 7.0"
67+
describe ".rails_compatibility" do
68+
it "returns empty output invalid rails version" do
69+
output = with_captured_stdout do
70+
NextRails::BundleReport.rails_compatibility(rails_version: nil)
7271
end
72+
expect(output).to be_empty
73+
end
74+
end
75+
76+
describe ".ruby_compatibility" do
77+
it "returns empty output invalid ruby version" do
78+
output = with_captured_stdout do
79+
NextRails::BundleReport.ruby_compatibility(ruby_version: nil)
80+
end
81+
expect(output).to be_empty
7382
end
7483
end
7584

spec/spec_helper.rb

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,3 +48,12 @@
4848
def with_env(env_hash)
4949
stub_const("ENV", ENV.to_hash.merge!(env_hash))
5050
end
51+
52+
def with_captured_stdout
53+
old_stdout = $stdout
54+
$stdout = StringIO.new
55+
yield
56+
$stdout.string
57+
ensure
58+
$stdout = old_stdout
59+
end

0 commit comments

Comments
 (0)