Skip to content

Commit 659dd5a

Browse files
justin808claude
andcommitted
Add react_on_rails:doctor generator for setup diagnostics
This commit introduces a comprehensive diagnostic command that helps users validate their React on Rails setup and identify configuration issues. Features: - Environment validation (Node.js, package managers, Git status) - Package validation (gem/npm versions, Shakapacker configuration) - Dependencies checking (React, Babel presets) - Rails integration validation (initializers, routes, controllers) - Webpack configuration analysis - Development environment checks (bundles, Procfiles, .gitignore) The doctor command provides colored output with detailed error messages, warnings, and success confirmations. It supports --verbose mode for detailed output and has proper exit codes for CI/automation use. The implementation includes: - SystemChecker module with reusable validation logic - DoctorGenerator with comprehensive checks and reporting - Complete test coverage for both components - Documentation updates in README and CHANGELOG Usage: rails generate react_on_rails:doctor [--verbose] 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
1 parent 99044da commit 659dd5a

File tree

7 files changed

+1130
-0
lines changed

7 files changed

+1130
-0
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ After a release, please make sure to run `bundle exec rake update_changelog`. Th
2323

2424
Changes since the last non-beta release.
2525

26+
#### Added
27+
- **`react_on_rails:doctor` generator**: New diagnostic command to validate React on Rails setup and identify configuration issues. Provides comprehensive checks for environment prerequisites, dependencies, Rails integration, and Webpack configuration. Use `rails generate react_on_rails:doctor` to diagnose your setup, with optional `--verbose` flag for detailed output.
28+
2629
### [16.0.0] - 2025-09-16
2730

2831
**React on Rails v16 is a major release that modernizes the library with ESM support, removes legacy Webpacker compatibility, and introduces significant performance improvements. This release builds on the foundation of v14 with enhanced RSC (React Server Components) support and streamlined configuration.**

README.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,16 @@ rails generate react_on_rails:install
6262
- `shakapacker.yml` settings
6363
- other configuration files
6464

65+
### Troubleshooting Setup Issues
66+
67+
If you encounter issues during installation or after upgrading, use the doctor command to diagnose your setup:
68+
69+
```bash
70+
rails generate react_on_rails:doctor
71+
```
72+
73+
The doctor command checks your environment, dependencies, and configuration files to identify potential issues. Use `--verbose` for detailed output.
74+
6575
For detailed upgrade instructions, see [upgrade guide documentation](docs/guides/upgrading-react-on-rails.md).
6676

6777
## React on Rails Pro
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
Description:
2+
The `react_on_rails:doctor` generator diagnoses your React on Rails setup
3+
and identifies potential configuration issues. It performs comprehensive
4+
checks on your environment, dependencies, and configuration files.
5+
6+
This command is especially useful for:
7+
• Troubleshooting setup issues
8+
• Verifying installation after running react_on_rails:install
9+
• Ensuring compatibility after upgrades
10+
• Getting help with configuration problems
11+
12+
Example:
13+
# Basic diagnosis
14+
rails generate react_on_rails:doctor
15+
16+
# Verbose output showing all checks
17+
rails generate react_on_rails:doctor --verbose
18+
19+
# Show help
20+
rails generate react_on_rails:doctor --help
21+
22+
Checks performed:
23+
Environment Prerequisites:
24+
• Node.js installation and version compatibility
25+
• JavaScript package manager availability (npm, yarn, pnpm, bun)
26+
• Git working directory status
27+
28+
React on Rails Packages:
29+
• React on Rails gem installation
30+
• react-on-rails NPM package installation
31+
• Version synchronization between gem and NPM package
32+
• Shakapacker configuration and installation
33+
34+
Dependencies:
35+
• React and React DOM installation
36+
• Babel preset configuration
37+
• Required development dependencies
38+
39+
Rails Integration:
40+
• React on Rails initializer configuration
41+
• Route and controller setup (Hello World example)
42+
• View helper integration
43+
44+
Webpack Configuration:
45+
• Webpack config file existence and structure
46+
• React on Rails compatibility checks
47+
• Environment-specific configuration validation
48+
49+
Development Environment:
50+
• JavaScript bundle files
51+
• Procfile.dev for development workflow
52+
• .gitignore configuration for generated files
53+
54+
Options:
55+
--verbose, -v: Show detailed output for all checks, including successful ones
56+
--fix, -f: Attempt to fix simple issues automatically (planned feature)
57+
58+
Exit codes:
59+
0: All checks passed or only warnings found
60+
1: Critical errors found that prevent React on Rails from working
61+
62+
For more help:
63+
• Documentation: https://github.com/shakacode/react_on_rails
64+
• Issues: https://github.com/shakacode/react_on_rails/issues
65+
• Discord: https://discord.gg/reactrails
Lines changed: 256 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,256 @@
1+
# frozen_string_literal: true
2+
3+
require "rails/generators"
4+
require "json"
5+
require_relative "system_checker"
6+
7+
begin
8+
require "rainbow"
9+
rescue LoadError
10+
# Fallback if Rainbow is not available
11+
class Rainbow
12+
def self.method_missing(_method, text)
13+
SimpleColorWrapper.new(text)
14+
end
15+
16+
def self.respond_to_missing?(_method, _include_private = false)
17+
true
18+
end
19+
end
20+
21+
class SimpleColorWrapper
22+
def initialize(text)
23+
@text = text
24+
end
25+
26+
def method_missing(_method, *_args)
27+
self
28+
end
29+
30+
def respond_to_missing?(_method, _include_private = false)
31+
true
32+
end
33+
34+
def to_s
35+
@text
36+
end
37+
end
38+
end
39+
40+
module ReactOnRails
41+
module Generators
42+
class DoctorGenerator < Rails::Generators::Base
43+
source_root(File.expand_path(__dir__))
44+
45+
desc "Diagnose React on Rails setup and configuration"
46+
47+
class_option :verbose,
48+
type: :boolean,
49+
default: false,
50+
desc: "Show detailed output for all checks",
51+
aliases: "-v"
52+
53+
class_option :fix,
54+
type: :boolean,
55+
default: false,
56+
desc: "Attempt to fix simple issues automatically (future feature)",
57+
aliases: "-f"
58+
59+
def run_diagnosis
60+
@checker = SystemChecker.new
61+
62+
print_header
63+
run_all_checks
64+
print_summary
65+
print_recommendations if @checker.errors? || @checker.warnings?
66+
67+
exit_with_status
68+
end
69+
70+
private
71+
72+
def print_header
73+
puts Rainbow("\n#{'=' * 80}").cyan
74+
puts Rainbow("🩺 REACT ON RAILS DOCTOR").cyan.bold
75+
puts Rainbow("Diagnosing your React on Rails setup...").cyan
76+
puts Rainbow("=" * 80).cyan
77+
puts
78+
end
79+
80+
def run_all_checks
81+
checks = [
82+
["Environment Prerequisites", :check_environment],
83+
["React on Rails Packages", :check_packages],
84+
["Dependencies", :check_dependencies],
85+
["Rails Integration", :check_rails],
86+
["Webpack Configuration", :check_webpack],
87+
["Development Environment", :check_development]
88+
]
89+
90+
checks.each do |section_name, check_method|
91+
print_section_header(section_name)
92+
send(check_method)
93+
puts
94+
end
95+
end
96+
97+
def print_section_header(section_name)
98+
puts Rainbow("#{section_name}:").blue.bold
99+
puts Rainbow("-" * (section_name.length + 1)).blue
100+
end
101+
102+
def check_environment
103+
@checker.check_node_installation
104+
@checker.check_package_manager
105+
@checker.check_git_status
106+
end
107+
108+
def check_packages
109+
@checker.check_react_on_rails_packages
110+
@checker.check_shakapacker_configuration
111+
end
112+
113+
def check_dependencies
114+
@checker.check_react_dependencies
115+
end
116+
117+
def check_rails
118+
@checker.check_rails_integration
119+
end
120+
121+
def check_webpack
122+
@checker.check_webpack_configuration
123+
end
124+
125+
def check_development
126+
check_javascript_bundles
127+
check_procfile_dev
128+
check_gitignore
129+
end
130+
131+
def check_javascript_bundles
132+
server_bundle = "app/javascript/packs/server-bundle.js"
133+
if File.exist?(server_bundle)
134+
@checker.add_success("✅ Server bundle file exists")
135+
else
136+
@checker.add_warning(<<~MSG.strip)
137+
⚠️ Server bundle not found: #{server_bundle}
138+
139+
This is required for server-side rendering.
140+
Run: rails generate react_on_rails:install
141+
MSG
142+
end
143+
end
144+
145+
def check_procfile_dev
146+
procfile_dev = "Procfile.dev"
147+
if File.exist?(procfile_dev)
148+
@checker.add_success("✅ Procfile.dev exists for development")
149+
check_procfile_content
150+
else
151+
@checker.add_info("ℹ️ Procfile.dev not found (optional for development)")
152+
end
153+
end
154+
155+
def check_procfile_content
156+
content = File.read("Procfile.dev")
157+
if content.include?("shakapacker-dev-server")
158+
@checker.add_success("✅ Procfile.dev includes webpack dev server")
159+
else
160+
@checker.add_info("ℹ️ Consider adding shakapacker-dev-server to Procfile.dev")
161+
end
162+
end
163+
164+
def check_gitignore
165+
gitignore_path = ".gitignore"
166+
return unless File.exist?(gitignore_path)
167+
168+
content = File.read(gitignore_path)
169+
if content.include?("**/generated/**")
170+
@checker.add_success("✅ .gitignore excludes generated files")
171+
else
172+
@checker.add_info("ℹ️ Consider adding '**/generated/**' to .gitignore")
173+
end
174+
end
175+
176+
def print_summary
177+
puts Rainbow("DIAGNOSIS COMPLETE").cyan.bold
178+
puts Rainbow("=" * 80).cyan
179+
puts
180+
181+
error_count = @checker.messages.count { |msg| msg[:type] == :error }
182+
warning_count = @checker.messages.count { |msg| msg[:type] == :warning }
183+
success_count = @checker.messages.count { |msg| msg[:type] == :success }
184+
185+
if error_count == 0 && warning_count == 0
186+
puts Rainbow("🎉 Excellent! Your React on Rails setup looks perfect!").green.bold
187+
elsif error_count == 0
188+
puts Rainbow("✅ Good! Your setup is functional with #{warning_count} minor issue(s).").yellow
189+
else
190+
puts Rainbow("❌ Issues found: #{error_count} error(s), #{warning_count} warning(s)").red
191+
end
192+
193+
puts Rainbow("📊 Summary: #{success_count} checks passed, #{warning_count} warnings, #{error_count} errors").blue
194+
195+
return unless options[:verbose] || error_count > 0 || warning_count > 0
196+
197+
puts "\nDetailed Results:"
198+
print_all_messages
199+
end
200+
201+
def print_all_messages
202+
@checker.messages.each do |message|
203+
color = case message[:type]
204+
when :error then :red
205+
when :warning then :yellow
206+
when :success then :green
207+
when :info then :blue
208+
end
209+
210+
puts Rainbow(message[:content]).send(color)
211+
puts
212+
end
213+
end
214+
215+
def print_recommendations
216+
puts Rainbow("RECOMMENDATIONS").cyan.bold
217+
puts Rainbow("=" * 80).cyan
218+
219+
if @checker.errors?
220+
puts Rainbow("Critical Issues:").red.bold
221+
puts "• Fix the errors above before proceeding"
222+
puts "• Run 'rails generate react_on_rails:install' to set up missing components"
223+
puts "• Ensure all prerequisites (Node.js, package manager) are installed"
224+
puts
225+
end
226+
227+
if @checker.has_warnings?
228+
puts Rainbow("Suggested Improvements:").yellow.bold
229+
puts "• Review warnings above for optimization opportunities"
230+
puts "• Consider updating packages to latest compatible versions"
231+
puts "• Check documentation for best practices"
232+
puts
233+
end
234+
235+
puts Rainbow("Next Steps:").blue.bold
236+
puts "• Run tests to verify everything works: bundle exec rspec"
237+
puts "• Start development server: ./bin/dev (if using Procfile.dev)"
238+
puts "• Check React on Rails documentation: https://github.com/shakacode/react_on_rails"
239+
puts
240+
end
241+
242+
def exit_with_status
243+
if @checker.errors?
244+
puts Rainbow("❌ Doctor found critical issues. Please address errors above.").red.bold
245+
exit(1)
246+
elsif @checker.warnings?
247+
puts Rainbow("⚠️ Doctor found some issues. Consider addressing warnings above.").yellow
248+
exit(0)
249+
else
250+
puts Rainbow("🎉 All checks passed! Your React on Rails setup is healthy.").green.bold
251+
exit(0)
252+
end
253+
end
254+
end
255+
end
256+
end

0 commit comments

Comments
 (0)