Skip to content

Commit ae90628

Browse files
justin808claude
andcommitted
Address code review feedback: improve validation skip logic
Improvements based on code review: 1. **Nil-safe ARGV check**: Use safe navigation operator and check for empty ARGV - Prevents errors when ARGV is empty or nil - More defensive against edge cases 2. **Refactored to extract methods**: Created testable class methods - skip_version_validation?() - main entry point - running_generator?() - checks if running Rails generator - package_json_missing?() - checks if package.json exists - Improves testability and code clarity 3. **Added debug logging**: Log when validation is skipped - "Skipping validation - package.json not found" - "Skipping validation during generator runtime" - Helps debugging and understanding behavior 4. **Optimized check order**: Check package.json existence first - File existence check is cheaper than ARGV inspection - Handles more cases (initial setup, generators, etc.) 5. **Comprehensive test coverage**: Added 15 test cases - Tests for package.json missing scenarios - Tests for generator detection (both "generate" and "g") - Tests for edge cases (empty ARGV, other commands) - Tests for each helper method All tests passing, RuboCop clean. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 3905a07 commit ae90628

File tree

2 files changed

+191
-7
lines changed

2 files changed

+191
-7
lines changed

lib/react_on_rails/engine.rb

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,20 +9,44 @@ class Engine < ::Rails::Engine
99
# Skip validation during installation tasks (e.g., shakapacker:install) or generator runtime
1010
initializer "react_on_rails.validate_version_and_package_compatibility" do
1111
config.after_initialize do
12-
# Skip validation when running Rails generators - they will install packages during execution
13-
running_generator = ARGV.first == "generate" || ARGV.first == "g"
14-
next if running_generator
15-
16-
# Skip validation if package.json doesn't exist yet (during initial setup)
17-
package_json = VersionChecker::NodePackageVersion.package_json_path
18-
next unless File.exist?(package_json)
12+
next if skip_version_validation?
1913

2014
Rails.logger.info "[React on Rails] Validating package version and compatibility..."
2115
VersionChecker.build.validate_version_and_package_compatibility!
2216
Rails.logger.info "[React on Rails] Package validation successful"
2317
end
2418
end
2519

20+
# Determine if version validation should be skipped
21+
# @return [Boolean] true if validation should be skipped
22+
def self.skip_version_validation?
23+
# Check package.json first as it's cheaper and handles more cases
24+
if package_json_missing?
25+
Rails.logger.debug "[React on Rails] Skipping validation - package.json not found"
26+
return true
27+
end
28+
29+
# Skip during generator runtime since packages are installed during execution
30+
if running_generator?
31+
Rails.logger.debug "[React on Rails] Skipping validation during generator runtime"
32+
return true
33+
end
34+
35+
false
36+
end
37+
38+
# Check if we're running a Rails generator
39+
# @return [Boolean] true if running a generator
40+
def self.running_generator?
41+
!ARGV.empty? && ARGV.first&.in?(%w[generate g])
42+
end
43+
44+
# Check if package.json doesn't exist yet
45+
# @return [Boolean] true if package.json is missing
46+
def self.package_json_missing?
47+
!File.exist?(VersionChecker::NodePackageVersion.package_json_path)
48+
end
49+
2650
config.to_prepare do
2751
ReactOnRails::ServerRenderingPool.reset_pool
2852
end

spec/react_on_rails/engine_spec.rb

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
# frozen_string_literal: true
2+
3+
require_relative "spec_helper"
4+
5+
module ReactOnRails
6+
RSpec.describe Engine do
7+
describe ".skip_version_validation?" do
8+
let(:package_json_path) { "/fake/path/package.json" }
9+
10+
before do
11+
allow(VersionChecker::NodePackageVersion).to receive(:package_json_path)
12+
.and_return(package_json_path)
13+
allow(Rails.logger).to receive(:debug)
14+
end
15+
16+
context "when package.json doesn't exist" do
17+
before do
18+
allow(File).to receive(:exist?).with(package_json_path).and_return(false)
19+
end
20+
21+
it "returns true" do
22+
expect(described_class.skip_version_validation?).to be true
23+
end
24+
25+
it "logs debug message about missing package.json" do
26+
described_class.skip_version_validation?
27+
expect(Rails.logger).to have_received(:debug)
28+
.with("[React on Rails] Skipping validation - package.json not found")
29+
end
30+
end
31+
32+
context "when package.json exists" do
33+
before do
34+
allow(File).to receive(:exist?).with(package_json_path).and_return(true)
35+
end
36+
37+
context "when running a generator" do
38+
before do
39+
stub_const("ARGV", ["generate", "react_on_rails:install"])
40+
end
41+
42+
it "returns true" do
43+
expect(described_class.skip_version_validation?).to be true
44+
end
45+
46+
it "logs debug message about generator runtime" do
47+
described_class.skip_version_validation?
48+
expect(Rails.logger).to have_received(:debug)
49+
.with("[React on Rails] Skipping validation during generator runtime")
50+
end
51+
end
52+
53+
context "when running a generator with short form" do
54+
before do
55+
stub_const("ARGV", ["g", "react_on_rails:install"])
56+
end
57+
58+
it "returns true" do
59+
expect(described_class.skip_version_validation?).to be true
60+
end
61+
end
62+
63+
context "when ARGV is empty" do
64+
before do
65+
stub_const("ARGV", [])
66+
end
67+
68+
it "returns false" do
69+
expect(described_class.skip_version_validation?).to be false
70+
end
71+
end
72+
73+
context "when running other commands" do
74+
%w[server console runner].each do |command|
75+
context "when running '#{command}'" do
76+
before do
77+
stub_const("ARGV", [command])
78+
end
79+
80+
it "returns false" do
81+
expect(described_class.skip_version_validation?).to be false
82+
end
83+
end
84+
end
85+
end
86+
end
87+
end
88+
89+
describe ".running_generator?" do
90+
context "when ARGV is empty" do
91+
before do
92+
stub_const("ARGV", [])
93+
end
94+
95+
it "returns false" do
96+
expect(described_class.running_generator?).to be false
97+
end
98+
end
99+
100+
context "when ARGV.first is 'generate'" do
101+
before do
102+
stub_const("ARGV", %w[generate model User])
103+
end
104+
105+
it "returns true" do
106+
expect(described_class.running_generator?).to be true
107+
end
108+
end
109+
110+
context "when ARGV.first is 'g'" do
111+
before do
112+
stub_const("ARGV", %w[g controller Users])
113+
end
114+
115+
it "returns true" do
116+
expect(described_class.running_generator?).to be true
117+
end
118+
end
119+
120+
context "when ARGV.first is another command" do
121+
before do
122+
stub_const("ARGV", ["server"])
123+
end
124+
125+
it "returns false" do
126+
expect(described_class.running_generator?).to be false
127+
end
128+
end
129+
end
130+
131+
describe ".package_json_missing?" do
132+
let(:package_json_path) { "/fake/path/package.json" }
133+
134+
before do
135+
allow(VersionChecker::NodePackageVersion).to receive(:package_json_path)
136+
.and_return(package_json_path)
137+
end
138+
139+
context "when package.json exists" do
140+
before do
141+
allow(File).to receive(:exist?).with(package_json_path).and_return(true)
142+
end
143+
144+
it "returns false" do
145+
expect(described_class.package_json_missing?).to be false
146+
end
147+
end
148+
149+
context "when package.json doesn't exist" do
150+
before do
151+
allow(File).to receive(:exist?).with(package_json_path).and_return(false)
152+
end
153+
154+
it "returns true" do
155+
expect(described_class.package_json_missing?).to be true
156+
end
157+
end
158+
end
159+
end
160+
end

0 commit comments

Comments
 (0)