class-metrix 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.rspec +3 -0
- data/.rubocop.yml +88 -0
- data/.tool-versions +1 -0
- data/CHANGELOG.md +41 -0
- data/LICENSE.txt +21 -0
- data/README.md +417 -0
- data/RELEASE_GUIDE.md +158 -0
- data/Rakefile +12 -0
- data/examples/README.md +155 -0
- data/examples/advanced/error_handling.rb +199 -0
- data/examples/advanced/hash_expansion.rb +180 -0
- data/examples/basic/01_simple_constants.rb +56 -0
- data/examples/basic/02_simple_methods.rb +99 -0
- data/examples/basic/03_multi_type_extraction.rb +116 -0
- data/examples/components/configurable_reports.rb +201 -0
- data/examples/csv_output_demo.rb +237 -0
- data/examples/real_world/microservices_audit.rb +312 -0
- data/lib/class_metrix/extractor.rb +121 -0
- data/lib/class_metrix/extractors/constants_extractor.rb +87 -0
- data/lib/class_metrix/extractors/methods_extractor.rb +87 -0
- data/lib/class_metrix/extractors/multi_type_extractor.rb +66 -0
- data/lib/class_metrix/formatters/base/base_component.rb +62 -0
- data/lib/class_metrix/formatters/base/base_formatter.rb +93 -0
- data/lib/class_metrix/formatters/components/footer_component.rb +67 -0
- data/lib/class_metrix/formatters/components/generic_header_component.rb +87 -0
- data/lib/class_metrix/formatters/components/header_component.rb +92 -0
- data/lib/class_metrix/formatters/components/missing_behaviors_component.rb +140 -0
- data/lib/class_metrix/formatters/components/table_component.rb +268 -0
- data/lib/class_metrix/formatters/csv_formatter.rb +98 -0
- data/lib/class_metrix/formatters/markdown_formatter.rb +184 -0
- data/lib/class_metrix/formatters/shared/csv_table_builder.rb +21 -0
- data/lib/class_metrix/formatters/shared/markdown_table_builder.rb +97 -0
- data/lib/class_metrix/formatters/shared/table_builder.rb +267 -0
- data/lib/class_metrix/formatters/shared/value_processor.rb +78 -0
- data/lib/class_metrix/processors/value_processor.rb +40 -0
- data/lib/class_metrix/utils/class_resolver.rb +20 -0
- data/lib/class_metrix/version.rb +5 -0
- data/lib/class_metrix.rb +12 -0
- data/sig/class/metrix.rbs +6 -0
- metadata +118 -0
data/RELEASE_GUIDE.md
ADDED
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
# Release Guide
|
|
2
|
+
|
|
3
|
+
This guide explains how to release new versions of the ClassMetrix gem.
|
|
4
|
+
|
|
5
|
+
## 🚀 Quick Release
|
|
6
|
+
|
|
7
|
+
For a simple patch release:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
# Using the release script (recommended)
|
|
11
|
+
./bin/release --type patch --push
|
|
12
|
+
|
|
13
|
+
# Or manually
|
|
14
|
+
./bin/release --type patch
|
|
15
|
+
# Then follow the printed instructions to commit and push
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## 📋 Prerequisites
|
|
19
|
+
|
|
20
|
+
Before creating a release, ensure you have:
|
|
21
|
+
|
|
22
|
+
1. **RubyGems API Key**: Set up in GitHub repository secrets as `RUBYGEMS_API_KEY`
|
|
23
|
+
2. **Clean working directory**: All changes committed
|
|
24
|
+
3. **Tests passing**: Run `bundle exec rake` to verify
|
|
25
|
+
4. **Updated documentation**: Ensure README and docs are current
|
|
26
|
+
|
|
27
|
+
## 🛠️ Release Process
|
|
28
|
+
|
|
29
|
+
### 1. Using the Release Script (Recommended)
|
|
30
|
+
|
|
31
|
+
The `bin/release` script automates version bumping and changelog updates:
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
# Patch release (0.1.0 → 0.1.1)
|
|
35
|
+
./bin/release --type patch
|
|
36
|
+
|
|
37
|
+
# Minor release (0.1.0 → 0.2.0)
|
|
38
|
+
./bin/release --type minor
|
|
39
|
+
|
|
40
|
+
# Major release (0.1.0 → 1.0.0)
|
|
41
|
+
./bin/release --type major
|
|
42
|
+
|
|
43
|
+
# Dry run to see what would happen
|
|
44
|
+
./bin/release --type patch --dry-run
|
|
45
|
+
|
|
46
|
+
# Automatic commit and push
|
|
47
|
+
./bin/release --type patch --push
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### 2. Manual Release Process
|
|
51
|
+
|
|
52
|
+
If you prefer to do it manually:
|
|
53
|
+
|
|
54
|
+
1. **Update Version**:
|
|
55
|
+
```ruby
|
|
56
|
+
# lib/class_metrix/version.rb
|
|
57
|
+
module ClassMetrix
|
|
58
|
+
VERSION = "0.1.1" # Increment appropriately
|
|
59
|
+
end
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
2. **Update CHANGELOG.md**:
|
|
63
|
+
```markdown
|
|
64
|
+
## [Unreleased]
|
|
65
|
+
|
|
66
|
+
## [0.1.1] - 2024-01-15
|
|
67
|
+
### Fixed
|
|
68
|
+
- Bug fixes and improvements
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
3. **Commit and Tag**:
|
|
72
|
+
```bash
|
|
73
|
+
git add -A
|
|
74
|
+
git commit -m "Release v0.1.1"
|
|
75
|
+
git tag v0.1.1
|
|
76
|
+
git push origin master
|
|
77
|
+
git push origin v0.1.1
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## 🤖 Automated Release Workflow
|
|
81
|
+
|
|
82
|
+
When you push a tag (e.g., `v0.1.1`), GitHub Actions automatically:
|
|
83
|
+
|
|
84
|
+
1. **Runs tests** across Ruby 3.1, 3.2, and 3.3
|
|
85
|
+
2. **Verifies version consistency** between tag and gemspec
|
|
86
|
+
3. **Builds the gem**
|
|
87
|
+
4. **Publishes to RubyGems**
|
|
88
|
+
5. **Creates a GitHub Release**
|
|
89
|
+
|
|
90
|
+
### Workflow Files
|
|
91
|
+
|
|
92
|
+
- **`.github/workflows/main.yml`**: CI pipeline for PRs and pushes
|
|
93
|
+
- **`.github/workflows/release.yml`**: Release automation for tags
|
|
94
|
+
|
|
95
|
+
## 🔑 Setting Up RubyGems API Key
|
|
96
|
+
|
|
97
|
+
1. **Generate API Key**:
|
|
98
|
+
```bash
|
|
99
|
+
gem signin
|
|
100
|
+
# Get your API key from ~/.gem/credentials
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
2. **Add to GitHub Secrets**:
|
|
104
|
+
- Go to your repo → Settings → Secrets and variables → Actions
|
|
105
|
+
- Add secret named `RUBYGEMS_API_KEY`
|
|
106
|
+
- Paste your API key as the value
|
|
107
|
+
|
|
108
|
+
## 📊 Release Checklist
|
|
109
|
+
|
|
110
|
+
Before each release:
|
|
111
|
+
|
|
112
|
+
- [ ] All tests pass (`bundle exec rake`)
|
|
113
|
+
- [ ] RuboCop passes (`bundle exec rubocop`)
|
|
114
|
+
- [ ] Documentation is updated
|
|
115
|
+
- [ ] CHANGELOG.md reflects new changes
|
|
116
|
+
- [ ] Version is bumped appropriately
|
|
117
|
+
- [ ] No TODO items in gemspec
|
|
118
|
+
- [ ] GitHub secrets are configured
|
|
119
|
+
|
|
120
|
+
## 🐛 Troubleshooting
|
|
121
|
+
|
|
122
|
+
### Version Mismatch Error
|
|
123
|
+
|
|
124
|
+
If the workflow fails with a version mismatch:
|
|
125
|
+
|
|
126
|
+
```
|
|
127
|
+
Version mismatch! Gemspec: 0.1.0, Tag: 0.1.1
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
Ensure the version in `lib/class_metrix/version.rb` matches your git tag.
|
|
131
|
+
|
|
132
|
+
### RubyGems Push Failed
|
|
133
|
+
|
|
134
|
+
Check that:
|
|
135
|
+
1. `RUBYGEMS_API_KEY` secret is set correctly
|
|
136
|
+
2. You have push permissions for the gem
|
|
137
|
+
3. The version doesn't already exist on RubyGems
|
|
138
|
+
|
|
139
|
+
### GitHub Release Failed
|
|
140
|
+
|
|
141
|
+
Ensure the `GITHUB_TOKEN` has sufficient permissions (this is usually automatic).
|
|
142
|
+
|
|
143
|
+
## 📈 Semantic Versioning
|
|
144
|
+
|
|
145
|
+
This project follows [Semantic Versioning](https://semver.org/):
|
|
146
|
+
|
|
147
|
+
- **PATCH** (`0.1.0` → `0.1.1`): Bug fixes, documentation updates
|
|
148
|
+
- **MINOR** (`0.1.0` → `0.2.0`): New features, backwards compatible
|
|
149
|
+
- **MAJOR** (`0.1.0` → `1.0.0`): Breaking changes
|
|
150
|
+
|
|
151
|
+
## 🎯 Post-Release
|
|
152
|
+
|
|
153
|
+
After a successful release:
|
|
154
|
+
|
|
155
|
+
1. **Verify on RubyGems**: Check that the new version appears on [rubygems.org](https://rubygems.org/gems/class-metrix)
|
|
156
|
+
2. **Test installation**: `gem install class-metrix -v X.X.X`
|
|
157
|
+
3. **Update dependencies**: In projects using the gem
|
|
158
|
+
4. **Announce**: Consider announcements on relevant channels
|
data/Rakefile
ADDED
data/examples/README.md
ADDED
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
# ClassMetrix Examples
|
|
2
|
+
|
|
3
|
+
This directory contains comprehensive examples demonstrating all features of the ClassMetrix gem, organized from basic to advanced real-world scenarios.
|
|
4
|
+
|
|
5
|
+
## 🎯 Quick Start
|
|
6
|
+
|
|
7
|
+
If you're new to ClassMetrix, start with the basic examples:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
# Run basic examples in order
|
|
11
|
+
ruby examples/basic/01_simple_constants.rb
|
|
12
|
+
ruby examples/basic/02_simple_methods.rb
|
|
13
|
+
ruby examples/basic/03_multi_type_extraction.rb
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## 📁 Directory Structure
|
|
17
|
+
|
|
18
|
+
### `/basic/` - Getting Started
|
|
19
|
+
Perfect for learning the core concepts and API.
|
|
20
|
+
|
|
21
|
+
- **`01_simple_constants.rb`** - Extract and compare constants across classes
|
|
22
|
+
- Basic constant extraction
|
|
23
|
+
- Filtering with regex and strings
|
|
24
|
+
- Understanding the output format
|
|
25
|
+
|
|
26
|
+
- **`02_simple_methods.rb`** - Extract and compare class methods
|
|
27
|
+
- Class method extraction
|
|
28
|
+
- Handling different return types (strings, numbers, booleans, arrays)
|
|
29
|
+
- Method filtering techniques
|
|
30
|
+
|
|
31
|
+
- **`03_multi_type_extraction.rb`** - Combine constants and methods in one table
|
|
32
|
+
- Multi-type extraction with Type column
|
|
33
|
+
- Comparing constants vs methods with similar names
|
|
34
|
+
- Understanding behavior differences
|
|
35
|
+
|
|
36
|
+
### `/advanced/` - Powerful Features
|
|
37
|
+
Advanced features for complex scenarios.
|
|
38
|
+
|
|
39
|
+
- **`hash_expansion.rb`** - Hash value expansion into sub-rows
|
|
40
|
+
- Normal vs expanded hash display
|
|
41
|
+
- Hash key comparison across classes
|
|
42
|
+
- Mixed data type handling
|
|
43
|
+
- Multi-type extraction with expansion
|
|
44
|
+
|
|
45
|
+
- **`error_handling.rb`** - Graceful error handling
|
|
46
|
+
- Methods that raise exceptions
|
|
47
|
+
- Missing constants and methods
|
|
48
|
+
- Boolean and nil value processing
|
|
49
|
+
- Error indicators and recovery
|
|
50
|
+
|
|
51
|
+
### `/real_world/` - Production Examples
|
|
52
|
+
Real-world scenarios you might encounter.
|
|
53
|
+
|
|
54
|
+
- **`microservices_audit.rb`** - Complete microservices configuration audit
|
|
55
|
+
- Service metadata comparison
|
|
56
|
+
- Feature flag consistency analysis
|
|
57
|
+
- Database and cache configuration audits
|
|
58
|
+
- Performance metrics comparison
|
|
59
|
+
- Security configuration analysis
|
|
60
|
+
|
|
61
|
+
## 🚀 Running Examples
|
|
62
|
+
|
|
63
|
+
Each example is self-contained and can be run independently:
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
# Run any example directly
|
|
67
|
+
ruby examples/basic/01_simple_constants.rb
|
|
68
|
+
ruby examples/advanced/hash_expansion.rb
|
|
69
|
+
ruby examples/real_world/microservices_audit.rb
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## 📊 Example Output
|
|
73
|
+
|
|
74
|
+
All examples generate markdown tables that look like this:
|
|
75
|
+
|
|
76
|
+
```markdown
|
|
77
|
+
| Constant | UserService | OrderService | PaymentService |
|
|
78
|
+
|--------------|-------------|--------------|----------------|
|
|
79
|
+
| SERVICE_NAME | user-service| order-service| payment-service|
|
|
80
|
+
| VERSION | 2.1.0 | 1.8.5 | 3.0.1 |
|
|
81
|
+
| PORT | 8001 | 8002 | 8003 |
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
With hash expansion:
|
|
85
|
+
```markdown
|
|
86
|
+
| Method | UserService | OrderService | PaymentService |
|
|
87
|
+
|----------------|-------------|--------------|----------------|
|
|
88
|
+
| database_config| 📋 7 keys | 📋 8 keys | 📋 8 keys |
|
|
89
|
+
| └─ host | user-db... | order-db... | payment-db... |
|
|
90
|
+
| └─ port | 5432 | 5432 | 5432 |
|
|
91
|
+
| └─ ssl | true | true | true |
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
## 🛠️ Building Your Own Examples
|
|
95
|
+
|
|
96
|
+
Use these examples as templates for your own analysis:
|
|
97
|
+
|
|
98
|
+
```ruby
|
|
99
|
+
require_relative "../lib/class_metrix"
|
|
100
|
+
|
|
101
|
+
# Define your classes...
|
|
102
|
+
class MyService
|
|
103
|
+
CONFIG_SETTING = "value"
|
|
104
|
+
|
|
105
|
+
def self.some_method
|
|
106
|
+
"result"
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
# Extract and compare
|
|
111
|
+
result = ClassMetrix.extract(:constants, :class_methods)
|
|
112
|
+
.from([MyService, AnotherService])
|
|
113
|
+
.filter(/CONFIG|method/)
|
|
114
|
+
.expand_hashes
|
|
115
|
+
.handle_errors
|
|
116
|
+
.to_markdown("my_analysis.md")
|
|
117
|
+
|
|
118
|
+
puts result
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
## 📝 Generated Reports
|
|
122
|
+
|
|
123
|
+
Many examples save their output to markdown files:
|
|
124
|
+
|
|
125
|
+
- `config_analysis_expanded.md` - Hash expansion demo output
|
|
126
|
+
- `error_analysis_report.md` - Error handling demo output
|
|
127
|
+
- `microservices_audit_report.md` - Complete microservices audit
|
|
128
|
+
- `service_analysis_report.md` - Service comparison report
|
|
129
|
+
|
|
130
|
+
## 🎓 Learning Path
|
|
131
|
+
|
|
132
|
+
1. **Start with Basic Examples** - Learn the core API and concepts
|
|
133
|
+
2. **Try Advanced Features** - Explore hash expansion and error handling
|
|
134
|
+
3. **Study Real-World Examples** - See practical applications
|
|
135
|
+
4. **Build Your Own** - Apply ClassMetrix to your specific use cases
|
|
136
|
+
|
|
137
|
+
## 💡 Use Case Ideas
|
|
138
|
+
|
|
139
|
+
- **Configuration Management**: Compare settings across environments
|
|
140
|
+
- **API Analysis**: Compare method signatures and return types
|
|
141
|
+
- **Feature Flag Audits**: Ensure consistency across services
|
|
142
|
+
- **Class Architecture Review**: Compare similar classes for consistency
|
|
143
|
+
- **Microservices Governance**: Standardize configurations across services
|
|
144
|
+
- **Legacy Code Analysis**: Understand differences between old and new implementations
|
|
145
|
+
|
|
146
|
+
## 🤝 Contributing Examples
|
|
147
|
+
|
|
148
|
+
Have a great ClassMetrix use case? Consider contributing an example!
|
|
149
|
+
|
|
150
|
+
1. Create a new file in the appropriate directory
|
|
151
|
+
2. Follow the existing example structure
|
|
152
|
+
3. Include clear comments and output explanations
|
|
153
|
+
4. Add an entry to this README
|
|
154
|
+
|
|
155
|
+
Happy analyzing! 🎉
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
require_relative "../../lib/class_metrix"
|
|
5
|
+
|
|
6
|
+
puts "=== Advanced Example: Error Handling ==="
|
|
7
|
+
puts
|
|
8
|
+
|
|
9
|
+
# Classes that demonstrate various error scenarios
|
|
10
|
+
class WorkingService
|
|
11
|
+
# Working constants
|
|
12
|
+
SERVICE_NAME = "working"
|
|
13
|
+
VERSION = "1.0.0"
|
|
14
|
+
ENABLED = true
|
|
15
|
+
|
|
16
|
+
# Working methods
|
|
17
|
+
def self.status
|
|
18
|
+
"healthy"
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def self.version
|
|
22
|
+
"1.0.0"
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def self.health_check
|
|
26
|
+
{ status: "ok", uptime: 12_345 }
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def self.enabled?
|
|
30
|
+
true
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
class PartiallyBrokenService
|
|
35
|
+
# Working constants
|
|
36
|
+
SERVICE_NAME = "partially_broken"
|
|
37
|
+
VERSION = "0.9.0"
|
|
38
|
+
# Missing ENABLED constant
|
|
39
|
+
|
|
40
|
+
# Working methods
|
|
41
|
+
def self.status
|
|
42
|
+
"degraded"
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def self.version
|
|
46
|
+
"0.9.0"
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# Broken method that raises an error
|
|
50
|
+
def self.health_check
|
|
51
|
+
raise StandardError, "Health check failed!"
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def self.enabled?
|
|
55
|
+
false
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# Method that returns nil
|
|
59
|
+
def self.uptime
|
|
60
|
+
nil
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# Method with complex error
|
|
64
|
+
def self.database_connection
|
|
65
|
+
raise ActiveRecord::ConnectionNotEstablished, "Database unavailable"
|
|
66
|
+
rescue NameError
|
|
67
|
+
# If ActiveRecord is not available, raise a different error
|
|
68
|
+
raise "Connection library not available"
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
class CompletelyBrokenService
|
|
73
|
+
# Has some constants
|
|
74
|
+
SERVICE_NAME = "broken"
|
|
75
|
+
# Missing VERSION and ENABLED
|
|
76
|
+
|
|
77
|
+
# Has working method
|
|
78
|
+
def self.status
|
|
79
|
+
"down"
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
# Missing version method
|
|
83
|
+
|
|
84
|
+
# Broken health_check
|
|
85
|
+
def self.health_check
|
|
86
|
+
raise NoMethodError, "Health monitoring not implemented"
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
# Method that raises during execution
|
|
90
|
+
def self.enabled?
|
|
91
|
+
some_undefined_variable.call
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
# Method that returns false
|
|
95
|
+
def self.deprecated?
|
|
96
|
+
true
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
puts "=== Service Classes Defined ==="
|
|
101
|
+
puts "WorkingService: All methods work"
|
|
102
|
+
puts "PartiallyBrokenService: Some methods fail"
|
|
103
|
+
puts "CompletelyBrokenService: Most methods fail"
|
|
104
|
+
puts
|
|
105
|
+
|
|
106
|
+
# 1. Extract without error handling (will raise errors)
|
|
107
|
+
puts "💥 1. WITHOUT ERROR HANDLING (This will show errors)"
|
|
108
|
+
puts "-" * 60
|
|
109
|
+
|
|
110
|
+
begin
|
|
111
|
+
result = ClassMetrix.extract(:class_methods)
|
|
112
|
+
.from([WorkingService, PartiallyBrokenService])
|
|
113
|
+
.filter(/health_check/)
|
|
114
|
+
.to_markdown
|
|
115
|
+
puts result
|
|
116
|
+
rescue StandardError => e
|
|
117
|
+
puts "❌ Error occurred: #{e.class.name}: #{e.message}"
|
|
118
|
+
end
|
|
119
|
+
puts
|
|
120
|
+
|
|
121
|
+
# 2. Extract with error handling
|
|
122
|
+
puts "🛡️ 2. WITH ERROR HANDLING (Graceful failure)"
|
|
123
|
+
puts "-" * 60
|
|
124
|
+
result = ClassMetrix.extract(:class_methods)
|
|
125
|
+
.from([WorkingService, PartiallyBrokenService, CompletelyBrokenService])
|
|
126
|
+
.handle_errors
|
|
127
|
+
.to_markdown
|
|
128
|
+
|
|
129
|
+
puts result
|
|
130
|
+
puts
|
|
131
|
+
|
|
132
|
+
# 3. Constants with missing values
|
|
133
|
+
puts "📋 3. CONSTANTS WITH MISSING VALUES"
|
|
134
|
+
puts "-" * 60
|
|
135
|
+
result = ClassMetrix.extract(:constants)
|
|
136
|
+
.from([WorkingService, PartiallyBrokenService, CompletelyBrokenService])
|
|
137
|
+
.handle_errors
|
|
138
|
+
.to_markdown
|
|
139
|
+
|
|
140
|
+
puts result
|
|
141
|
+
puts
|
|
142
|
+
|
|
143
|
+
# 4. Multi-type extraction with errors
|
|
144
|
+
puts "📊 4. MULTI-TYPE WITH ERROR HANDLING"
|
|
145
|
+
puts "-" * 60
|
|
146
|
+
result = ClassMetrix.extract(:constants, :class_methods)
|
|
147
|
+
.from([WorkingService, PartiallyBrokenService, CompletelyBrokenService])
|
|
148
|
+
.filter(/SERVICE_NAME|status|enabled/)
|
|
149
|
+
.handle_errors
|
|
150
|
+
.to_markdown
|
|
151
|
+
|
|
152
|
+
puts result
|
|
153
|
+
puts
|
|
154
|
+
|
|
155
|
+
# 5. Focus on problematic methods
|
|
156
|
+
puts "🔍 5. PROBLEMATIC METHODS ANALYSIS"
|
|
157
|
+
puts "-" * 60
|
|
158
|
+
result = ClassMetrix.extract(:class_methods)
|
|
159
|
+
.from([WorkingService, PartiallyBrokenService, CompletelyBrokenService])
|
|
160
|
+
.filter(/health_check|database|uptime/)
|
|
161
|
+
.handle_errors
|
|
162
|
+
.to_markdown
|
|
163
|
+
|
|
164
|
+
puts result
|
|
165
|
+
puts
|
|
166
|
+
|
|
167
|
+
# 6. Boolean and nil value handling
|
|
168
|
+
puts "✅ 6. BOOLEAN AND NIL VALUE HANDLING"
|
|
169
|
+
puts "-" * 60
|
|
170
|
+
result = ClassMetrix.extract(:class_methods)
|
|
171
|
+
.from([WorkingService, PartiallyBrokenService, CompletelyBrokenService])
|
|
172
|
+
.filter(/enabled\?|deprecated\?|uptime/)
|
|
173
|
+
.handle_errors
|
|
174
|
+
.to_markdown
|
|
175
|
+
|
|
176
|
+
puts result
|
|
177
|
+
puts
|
|
178
|
+
|
|
179
|
+
# 7. Save comprehensive error analysis report
|
|
180
|
+
puts "💾 7. SAVING COMPREHENSIVE ERROR ANALYSIS REPORT"
|
|
181
|
+
puts "-" * 60
|
|
182
|
+
report = ClassMetrix.extract(:constants, :class_methods)
|
|
183
|
+
.from([WorkingService, PartiallyBrokenService, CompletelyBrokenService])
|
|
184
|
+
.handle_errors
|
|
185
|
+
.to_markdown("error_analysis_report.md", title: "Service Health Analysis Report")
|
|
186
|
+
|
|
187
|
+
puts "✅ Comprehensive error analysis saved to: error_analysis_report.md"
|
|
188
|
+
puts "📊 Report contains #{report.lines.count} lines with rich metadata"
|
|
189
|
+
puts
|
|
190
|
+
|
|
191
|
+
puts "🛡️ Enhanced Error Handling Features Demonstrated:"
|
|
192
|
+
puts "• 🚫 Missing constants: '🚫 Not defined'"
|
|
193
|
+
puts "• 🚫 Missing methods: '🚫 No method'"
|
|
194
|
+
puts "• ⚠️ Runtime errors: '⚠️ Error: [descriptive message]'"
|
|
195
|
+
puts "• ❌ Boolean false and nil values: '❌'"
|
|
196
|
+
puts "• ✅ Boolean true values: '✅'"
|
|
197
|
+
puts "• 📊 Rich markdown reports with titles and metadata"
|
|
198
|
+
puts "• 📋 Missing behaviors summary per class"
|
|
199
|
+
puts "• 🛡️ handle_errors flag enables graceful degradation"
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
require_relative "../../lib/class_metrix"
|
|
5
|
+
|
|
6
|
+
puts "=== Advanced Example: Hash Expansion ==="
|
|
7
|
+
puts
|
|
8
|
+
|
|
9
|
+
# Configuration classes with complex hash structures
|
|
10
|
+
class DatabaseConfig
|
|
11
|
+
# Hash constants
|
|
12
|
+
DEFAULT_CONFIG = {
|
|
13
|
+
host: "localhost",
|
|
14
|
+
port: 5432,
|
|
15
|
+
ssl: true,
|
|
16
|
+
pool_size: 5
|
|
17
|
+
}.freeze
|
|
18
|
+
|
|
19
|
+
CONNECTION_POOLS = {
|
|
20
|
+
read: { size: 10, timeout: 30 },
|
|
21
|
+
write: { size: 5, timeout: 15 },
|
|
22
|
+
admin: { size: 2, timeout: 60 }
|
|
23
|
+
}.freeze
|
|
24
|
+
|
|
25
|
+
# Hash methods
|
|
26
|
+
def self.production_config
|
|
27
|
+
{
|
|
28
|
+
host: "db.production.com",
|
|
29
|
+
port: 5432,
|
|
30
|
+
database: "myapp_production",
|
|
31
|
+
ssl: true,
|
|
32
|
+
pool_size: 20,
|
|
33
|
+
timeout: 30,
|
|
34
|
+
backup_enabled: true
|
|
35
|
+
}
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def self.development_config
|
|
39
|
+
{
|
|
40
|
+
host: "localhost",
|
|
41
|
+
port: 5432,
|
|
42
|
+
database: "myapp_development",
|
|
43
|
+
ssl: false,
|
|
44
|
+
pool_size: 5,
|
|
45
|
+
timeout: 10
|
|
46
|
+
}
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def self.simple_value
|
|
50
|
+
"not a hash"
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
class RedisConfig
|
|
55
|
+
# Hash constants
|
|
56
|
+
DEFAULT_CONFIG = {
|
|
57
|
+
host: "localhost",
|
|
58
|
+
port: 6379,
|
|
59
|
+
ssl: false,
|
|
60
|
+
timeout: 5
|
|
61
|
+
}.freeze
|
|
62
|
+
|
|
63
|
+
CLUSTER_CONFIG = {
|
|
64
|
+
nodes: 3,
|
|
65
|
+
replication: true,
|
|
66
|
+
failover: "auto"
|
|
67
|
+
}.freeze
|
|
68
|
+
|
|
69
|
+
# Hash methods
|
|
70
|
+
def self.production_config
|
|
71
|
+
{
|
|
72
|
+
host: "redis.internal",
|
|
73
|
+
port: 6379,
|
|
74
|
+
database: 0,
|
|
75
|
+
ssl: false,
|
|
76
|
+
max_connections: 100,
|
|
77
|
+
cluster_enabled: true
|
|
78
|
+
}
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def self.development_config
|
|
82
|
+
{
|
|
83
|
+
host: "localhost",
|
|
84
|
+
port: 6379,
|
|
85
|
+
database: 1,
|
|
86
|
+
ssl: false,
|
|
87
|
+
max_connections: 10
|
|
88
|
+
}
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def self.simple_value
|
|
92
|
+
42
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
puts "=== Configuration Classes Defined ==="
|
|
97
|
+
puts "DatabaseConfig and RedisConfig with hash constants and methods"
|
|
98
|
+
puts
|
|
99
|
+
|
|
100
|
+
# 1. Normal output (without expansion)
|
|
101
|
+
puts "📋 1. NORMAL OUTPUT (Hashes as inspect strings)"
|
|
102
|
+
puts "-" * 60
|
|
103
|
+
result = ClassMetrix.extract(:class_methods)
|
|
104
|
+
.from([DatabaseConfig, RedisConfig])
|
|
105
|
+
.filter(/config$/)
|
|
106
|
+
.to_markdown
|
|
107
|
+
|
|
108
|
+
puts result
|
|
109
|
+
puts
|
|
110
|
+
|
|
111
|
+
# 2. Expanded output
|
|
112
|
+
puts "🔍 2. EXPANDED OUTPUT (Hash keys as sub-rows)"
|
|
113
|
+
puts "-" * 60
|
|
114
|
+
result = ClassMetrix.extract(:class_methods)
|
|
115
|
+
.from([DatabaseConfig, RedisConfig])
|
|
116
|
+
.filter(/config$/)
|
|
117
|
+
.expand_hashes
|
|
118
|
+
.to_markdown
|
|
119
|
+
|
|
120
|
+
puts result
|
|
121
|
+
puts
|
|
122
|
+
|
|
123
|
+
# 3. Constants with expansion
|
|
124
|
+
puts "📊 3. CONSTANTS WITH HASH EXPANSION"
|
|
125
|
+
puts "-" * 60
|
|
126
|
+
result = ClassMetrix.extract(:constants)
|
|
127
|
+
.from([DatabaseConfig, RedisConfig])
|
|
128
|
+
.filter(/CONFIG/)
|
|
129
|
+
.expand_hashes
|
|
130
|
+
.handle_errors
|
|
131
|
+
.to_markdown
|
|
132
|
+
|
|
133
|
+
puts result
|
|
134
|
+
puts
|
|
135
|
+
|
|
136
|
+
# 4. Mixed data types with expansion
|
|
137
|
+
puts "🔧 4. MIXED DATA TYPES WITH EXPANSION"
|
|
138
|
+
puts "-" * 60
|
|
139
|
+
result = ClassMetrix.extract(:class_methods)
|
|
140
|
+
.from([DatabaseConfig, RedisConfig])
|
|
141
|
+
.expand_hashes
|
|
142
|
+
.to_markdown
|
|
143
|
+
|
|
144
|
+
puts result
|
|
145
|
+
puts
|
|
146
|
+
|
|
147
|
+
# 5. Multi-type extraction with expansion
|
|
148
|
+
puts "🚀 5. MULTI-TYPE WITH HASH EXPANSION"
|
|
149
|
+
puts "-" * 60
|
|
150
|
+
result = ClassMetrix.extract(:constants, :class_methods)
|
|
151
|
+
.from([DatabaseConfig, RedisConfig])
|
|
152
|
+
.filter(/DEFAULT_CONFIG|production_config/)
|
|
153
|
+
.expand_hashes
|
|
154
|
+
.handle_errors
|
|
155
|
+
.to_markdown
|
|
156
|
+
|
|
157
|
+
puts result
|
|
158
|
+
puts
|
|
159
|
+
|
|
160
|
+
# 6. Save expanded report
|
|
161
|
+
puts "💾 6. SAVING EXPANDED REPORT"
|
|
162
|
+
puts "-" * 60
|
|
163
|
+
report = ClassMetrix.extract(:constants, :class_methods)
|
|
164
|
+
.from([DatabaseConfig, RedisConfig])
|
|
165
|
+
.expand_hashes
|
|
166
|
+
.handle_errors
|
|
167
|
+
.to_markdown("config_analysis_expanded.md")
|
|
168
|
+
|
|
169
|
+
puts "✅ Expanded report saved to: config_analysis_expanded.md"
|
|
170
|
+
puts "📊 Report contains #{report.lines.count} lines"
|
|
171
|
+
puts
|
|
172
|
+
|
|
173
|
+
puts "✨ Hash Expansion Features Demonstrated:"
|
|
174
|
+
puts "• 📋 Hash indicators show number of keys"
|
|
175
|
+
puts "• └─ Sub-rows show individual key-value pairs"
|
|
176
|
+
puts "• ❌ Missing keys shown clearly"
|
|
177
|
+
puts "• — Non-hash values shown with dash"
|
|
178
|
+
puts "• Mixed data types handled properly"
|
|
179
|
+
puts "• Works with both constants and methods"
|
|
180
|
+
puts "• Compatible with multi-type extraction"
|