class-metrix 1.0.0 → 1.1.0
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 +4 -4
- data/.prettierrc.json +41 -0
- data/.qlty/.gitignore +7 -0
- data/.qlty/configs/.yamllint.yaml +8 -0
- data/.qlty/qlty.toml +108 -0
- data/.rubocop.yml +31 -25
- data/.vscode/README.md +255 -47
- data/.vscode/extensions.json +8 -13
- data/.vscode/keybindings.json +0 -0
- data/.vscode/settings.json +81 -11
- data/.vscode/tasks.json +231 -0
- data/CHANGELOG.md +33 -1
- data/README.md +107 -23
- data/Rakefile +64 -1
- data/Steepfile +26 -0
- data/config/brakeman.yml +37 -0
- data/docs/ARCHITECTURE.md +90 -48
- data/docs/CHANGELOG_EVOLUTION_EXAMPLE.md +95 -0
- data/docs/QLTY_INTEGRATION.md +181 -0
- data/docs/RELEASE_GUIDE.md +318 -0
- data/docs/SLACK_INTEGRATION.md +227 -0
- data/examples/README.md +23 -17
- data/examples/basic_usage.rb +19 -19
- data/examples/debug_levels_demo.rb +15 -16
- data/examples/debug_mode_demo.rb +12 -13
- data/examples/inheritance_and_modules.rb +45 -45
- data/lib/class_metrix/extractor.rb +1 -1
- data/lib/class_metrix/extractors/constants_extractor.rb +1 -1
- data/lib/class_metrix/extractors/methods_extractor.rb +1 -1
- data/lib/class_metrix/extractors/multi_type_extractor.rb +2 -2
- data/lib/class_metrix/formatters/base/base_formatter.rb +3 -3
- data/lib/class_metrix/formatters/components/footer_component.rb +3 -3
- data/lib/class_metrix/formatters/components/generic_header_component.rb +2 -2
- data/lib/class_metrix/formatters/components/header_component.rb +4 -4
- data/lib/class_metrix/formatters/components/missing_behaviors_component.rb +7 -7
- data/lib/class_metrix/formatters/components/table_component/row_processor.rb +8 -5
- data/lib/class_metrix/formatters/components/table_component/table_data_extractor.rb +4 -1
- data/lib/class_metrix/formatters/components/table_component/table_renderer.rb +2 -2
- data/lib/class_metrix/formatters/components/table_component.rb +5 -4
- data/lib/class_metrix/formatters/csv_formatter.rb +3 -3
- data/lib/class_metrix/formatters/markdown_formatter.rb +3 -4
- data/lib/class_metrix/formatters/shared/markdown_table_builder.rb +2 -2
- data/lib/class_metrix/formatters/shared/table_builder.rb +8 -6
- data/lib/class_metrix/version.rb +1 -1
- data/sig/class_metrix.rbs +8 -0
- data/sig/extractor.rbs +54 -0
- data/sig/extractors.rbs +84 -0
- data/sig/formatters_base.rbs +59 -0
- data/sig/formatters_components.rbs +133 -0
- data/sig/formatters_main.rbs +20 -0
- data/sig/formatters_shared.rbs +102 -0
- data/sig/manifest.yaml +32 -0
- data/sig/utils.rbs +57 -0
- data/sig/value_processor.rbs +11 -0
- data/sig/version.rbs +4 -0
- metadata +94 -4
- data/RELEASE_GUIDE.md +0 -158
- data/sig/class/metrix.rbs +0 -6
@@ -0,0 +1,227 @@
|
|
1
|
+
# Slack Integration for ClassMetrix CI/CD
|
2
|
+
|
3
|
+
This document explains how to set up Slack notifications for ClassMetrix GitHub Actions workflows.
|
4
|
+
|
5
|
+
## Overview
|
6
|
+
|
7
|
+
ClassMetrix uses Slack notifications to keep your team informed about CI/CD pipeline status. The integration provides minimal, focused notifications:
|
8
|
+
|
9
|
+
- **CI Pipeline**: One notification when the entire CI pipeline completes (success/failure/partial)
|
10
|
+
- **Release Pipeline**: One notification for release success, one for release failure
|
11
|
+
|
12
|
+
All notifications are sent to a single channel: `#cicd-notifications`
|
13
|
+
|
14
|
+
## Features
|
15
|
+
|
16
|
+
### CI Notifications
|
17
|
+
|
18
|
+
- ✅ **Pipeline Status**: Overall CI result with individual job statuses
|
19
|
+
- 🔗 **Direct Links**: Links to workflow runs and repository
|
20
|
+
- 📊 **Job Breakdown**: Status of tests, security, quality, and compatibility checks
|
21
|
+
- 🎯 **Contextual Info**: Branch, trigger type, and repository details
|
22
|
+
|
23
|
+
### Release Notifications
|
24
|
+
|
25
|
+
- 🚀 **Release Success**: Version info, installation commands, and useful links
|
26
|
+
- ❌ **Release Failure**: Detailed failure information and troubleshooting context
|
27
|
+
- 📦 **RubyGems Links**: Direct links to published gems
|
28
|
+
- 📚 **GitHub Release**: Links to release notes and documentation
|
29
|
+
|
30
|
+
## Setup Instructions
|
31
|
+
|
32
|
+
### 1. Create Slack Webhook
|
33
|
+
|
34
|
+
1. Go to your Slack workspace
|
35
|
+
2. Navigate to **Apps** → **Incoming Webhooks**
|
36
|
+
3. Click **Add to Slack**
|
37
|
+
4. Choose the `#cicd-notifications` channel (create it if it doesn't exist)
|
38
|
+
5. Copy the webhook URL (starts with `https://hooks.slack.com/services/...`)
|
39
|
+
|
40
|
+
### 2. Add GitHub Secret
|
41
|
+
|
42
|
+
1. Go to your GitHub repository: `https://github.com/patrick204nqh/class-metrix`
|
43
|
+
2. Navigate to **Settings** → **Secrets and variables** → **Actions**
|
44
|
+
3. Click **New repository secret**
|
45
|
+
4. Name: `SLACK_WEBHOOK_URL`
|
46
|
+
5. Value: Your Slack webhook URL
|
47
|
+
6. Click **Add secret**
|
48
|
+
|
49
|
+
### 3. Create Slack Channel
|
50
|
+
|
51
|
+
Create a `#cicd-notifications` channel in your Slack workspace where all CI/CD notifications will be posted.
|
52
|
+
|
53
|
+
## Notification Examples
|
54
|
+
|
55
|
+
### CI Pipeline Complete (Success)
|
56
|
+
|
57
|
+
```
|
58
|
+
✅ CI Pipeline Complete
|
59
|
+
Repository: your-org/class-metrix
|
60
|
+
Branch: main
|
61
|
+
Trigger: push
|
62
|
+
Status: success
|
63
|
+
Tests: success
|
64
|
+
Security: success
|
65
|
+
Quality: success
|
66
|
+
Compatibility: success
|
67
|
+
```
|
68
|
+
|
69
|
+
### CI Pipeline Complete (Failure)
|
70
|
+
|
71
|
+
```
|
72
|
+
❌ CI Pipeline Complete
|
73
|
+
Repository: your-org/class-metrix
|
74
|
+
Branch: feature-branch
|
75
|
+
Trigger: pull_request
|
76
|
+
Status: failure
|
77
|
+
Tests: failure
|
78
|
+
Security: success
|
79
|
+
Quality: success
|
80
|
+
Compatibility: success
|
81
|
+
```
|
82
|
+
|
83
|
+
### Release Success
|
84
|
+
|
85
|
+
```
|
86
|
+
🚀 ClassMetrix Release Complete
|
87
|
+
Version: v1.2.3
|
88
|
+
Trigger: Manual
|
89
|
+
Installation: gem install class-metrix -v 1.2.3
|
90
|
+
Links: 📦 RubyGems • 📚 GitHub Release
|
91
|
+
```
|
92
|
+
|
93
|
+
### Release Failure
|
94
|
+
|
95
|
+
```
|
96
|
+
❌ ClassMetrix Release Failed
|
97
|
+
Failed Step: Build & Publish
|
98
|
+
Version: v1.2.3
|
99
|
+
Reason: Gem build or RubyGems publishing failed
|
100
|
+
Repository: your-org/class-metrix
|
101
|
+
Workflow Run: View Logs
|
102
|
+
Triggered By: username
|
103
|
+
```
|
104
|
+
|
105
|
+
## Workflow Integration
|
106
|
+
|
107
|
+
### Main CI Workflow (`.github/workflows/main.yml`)
|
108
|
+
|
109
|
+
- Runs on push to main/master and pull requests
|
110
|
+
- Sends one notification after all jobs complete
|
111
|
+
- Includes status of: tests, security scan, quality checks, compatibility
|
112
|
+
- Only sends notifications if `SLACK_WEBHOOK_URL` secret is configured
|
113
|
+
|
114
|
+
### Release Workflow (`.github/workflows/release.yml`)
|
115
|
+
|
116
|
+
- Runs on version tags or manual dispatch
|
117
|
+
- Sends success notification with installation instructions and links
|
118
|
+
- Sends failure notification with detailed troubleshooting information
|
119
|
+
- Includes RubyGems and GitHub release links
|
120
|
+
|
121
|
+
## Testing the Integration
|
122
|
+
|
123
|
+
### Test CI Notifications
|
124
|
+
|
125
|
+
1. Make a small change to your code
|
126
|
+
2. Push to a branch or create a pull request
|
127
|
+
3. Check the `#cicd-notifications` channel for the CI completion message
|
128
|
+
|
129
|
+
### Test Release Notifications
|
130
|
+
|
131
|
+
1. Create a test release using workflow dispatch:
|
132
|
+
```bash
|
133
|
+
# Go to Actions → Release Gem → Run workflow
|
134
|
+
# Enable "Dry run" to test without publishing
|
135
|
+
```
|
136
|
+
2. Check the channel for release notifications
|
137
|
+
|
138
|
+
### Manual Testing Script
|
139
|
+
|
140
|
+
You can test the Slack webhook directly:
|
141
|
+
|
142
|
+
```bash
|
143
|
+
#!/bin/bash
|
144
|
+
# Save as bin/test_slack_integration
|
145
|
+
|
146
|
+
WEBHOOK_URL="YOUR_SLACK_WEBHOOK_URL"
|
147
|
+
|
148
|
+
curl -X POST -H 'Content-type: application/json' \
|
149
|
+
--data '{
|
150
|
+
"channel": "#cicd-notifications",
|
151
|
+
"username": "GitHub Actions CI",
|
152
|
+
"icon_emoji": ":robot_face:",
|
153
|
+
"text": "🧪 Testing Slack integration for ClassMetrix CI/CD"
|
154
|
+
}' \
|
155
|
+
"$WEBHOOK_URL"
|
156
|
+
```
|
157
|
+
|
158
|
+
## Troubleshooting
|
159
|
+
|
160
|
+
### No Notifications Received
|
161
|
+
|
162
|
+
1. **Check Secret**: Verify `SLACK_WEBHOOK_URL` is set correctly in GitHub repository secrets
|
163
|
+
2. **Check Channel**: Ensure `#cicd-notifications` channel exists and webhook has access
|
164
|
+
3. **Check Webhook**: Test webhook URL manually using curl or Postman
|
165
|
+
4. **Check Logs**: View workflow run logs for any Slack notification errors
|
166
|
+
|
167
|
+
### Webhook URL Issues
|
168
|
+
|
169
|
+
- Ensure the URL starts with `https://hooks.slack.com/services/`
|
170
|
+
- Verify the webhook is still active in Slack settings
|
171
|
+
- Check that the webhook has permission to post to the channel
|
172
|
+
|
173
|
+
### Missing Notifications
|
174
|
+
|
175
|
+
- Notifications only send if workflows complete (not cancelled mid-run)
|
176
|
+
- CI notifications require all jobs to finish (test, security, quality, compatibility)
|
177
|
+
- Release notifications only send if `dry_run` is not enabled
|
178
|
+
|
179
|
+
## Customization
|
180
|
+
|
181
|
+
### Changing the Channel
|
182
|
+
|
183
|
+
To send notifications to a different channel, update the `"channel"` field in both workflow files:
|
184
|
+
|
185
|
+
```yaml
|
186
|
+
"channel": "#your-custom-channel"
|
187
|
+
```
|
188
|
+
|
189
|
+
### Adding More Notifications
|
190
|
+
|
191
|
+
The current setup provides minimal notifications. To add more:
|
192
|
+
|
193
|
+
1. Review the conversation summary for previously removed notifications
|
194
|
+
2. Add new notification steps to appropriate workflow jobs
|
195
|
+
3. Follow the same webhook format for consistency
|
196
|
+
|
197
|
+
### Notification Format
|
198
|
+
|
199
|
+
All notifications use Slack's rich attachment format with:
|
200
|
+
|
201
|
+
- Color coding (green for success, red for failure, yellow for warnings)
|
202
|
+
- Structured fields for easy scanning
|
203
|
+
- Direct links to relevant resources
|
204
|
+
- Contextual information (branch, trigger, repository)
|
205
|
+
|
206
|
+
## Security Considerations
|
207
|
+
|
208
|
+
- **Webhook URL**: Keep the `SLACK_WEBHOOK_URL` secret secure
|
209
|
+
- **Channel Access**: Ensure only appropriate team members have access to the notifications channel
|
210
|
+
- **Information Exposure**: Current notifications don't expose sensitive code or secrets
|
211
|
+
- **Rate Limiting**: Slack has rate limits for webhook calls (not typically an issue with minimal notifications)
|
212
|
+
|
213
|
+
## Support
|
214
|
+
|
215
|
+
For issues with Slack integration:
|
216
|
+
|
217
|
+
1. Check this documentation first
|
218
|
+
2. Review GitHub Actions workflow logs
|
219
|
+
3. Test webhook URL manually
|
220
|
+
4. Verify Slack workspace permissions
|
221
|
+
5. Create an issue in the ClassMetrix repository if problems persist
|
222
|
+
|
223
|
+
## Related Documentation
|
224
|
+
|
225
|
+
- [GitHub Actions Documentation](https://docs.github.com/en/actions)
|
226
|
+
- [Slack Incoming Webhooks](https://api.slack.com/messaging/webhooks)
|
227
|
+
- [ClassMetrix Release Guide](./RELEASE_GUIDE.md)
|
data/examples/README.md
CHANGED
@@ -16,6 +16,7 @@ ruby examples/inheritance_and_modules.rb # Inheritance and module analysis
|
|
16
16
|
### Core Examples
|
17
17
|
|
18
18
|
- **`basic_usage.rb`** - Basic constant and method extraction
|
19
|
+
|
19
20
|
- Simple class comparison
|
20
21
|
- Filtering and multi-type extraction
|
21
22
|
- Hash expansion basics
|
@@ -122,43 +123,48 @@ ClassMetrix.extract(:constants)
|
|
122
123
|
## 📊 Example Output
|
123
124
|
|
124
125
|
### Basic Comparison
|
126
|
+
|
125
127
|
```markdown
|
126
|
-
| Constant | User
|
127
|
-
|
128
|
-
| ROLE | user
|
129
|
-
| TIMEOUT | 3600
|
128
|
+
| Constant | User | Admin |
|
129
|
+
| -------- | ---- | ----- |
|
130
|
+
| ROLE | user | admin |
|
131
|
+
| TIMEOUT | 3600 | 7200 |
|
130
132
|
```
|
131
133
|
|
132
134
|
### With Inheritance
|
135
|
+
|
133
136
|
```markdown
|
134
|
-
| Constant
|
135
|
-
|
136
|
-
| SERVICE_NAME
|
137
|
-
| SERVICE_VERSION| 1.0
|
138
|
-
| DEFAULT_TIMEOUT| 30
|
137
|
+
| Constant | DatabaseService | CacheService |
|
138
|
+
| --------------- | --------------- | ------------ |
|
139
|
+
| SERVICE_NAME | database | cache |
|
140
|
+
| SERVICE_VERSION | 1.0 | 1.0 |
|
141
|
+
| DEFAULT_TIMEOUT | 30 | 30 |
|
139
142
|
```
|
140
143
|
|
141
144
|
### Hash Expansion
|
145
|
+
|
142
146
|
```markdown
|
143
|
-
| Method
|
144
|
-
|
145
|
-
| config
|
146
|
-
| config.host
|
147
|
-
| config.port
|
148
|
-
| config.ssl
|
147
|
+
| Method | Service1 | Service2 |
|
148
|
+
| ----------- | --------- | -------------- |
|
149
|
+
| config | {...} | {...} |
|
150
|
+
| config.host | localhost | production.com |
|
151
|
+
| config.port | 3000 | 443 |
|
152
|
+
| config.ssl | ❌ | ✅ |
|
149
153
|
```
|
150
154
|
|
151
155
|
## 🛠️ API Reference
|
152
156
|
|
153
157
|
### Extraction Types
|
158
|
+
|
154
159
|
- `:constants` - Class constants
|
155
160
|
- `:class_methods` - Class methods
|
156
161
|
|
157
162
|
### Options
|
163
|
+
|
158
164
|
- `.from(classes)` - Classes to analyze (array)
|
159
165
|
- `.filter(pattern)` - Filter by name (regex or string)
|
160
166
|
- `.include_inherited` - Include parent class behaviors
|
161
|
-
- `.include_modules` - Include module behaviors
|
167
|
+
- `.include_modules` - Include module behaviors
|
162
168
|
- `.include_all` - Include inherited + modules
|
163
169
|
- `.expand_hashes` - Expand hash values (shows main rows by default)
|
164
170
|
- `.show_only_main` - Show only main rows (collapsed hashes) - **Default**
|
@@ -197,6 +203,6 @@ ruby examples/inheritance_and_modules.rb
|
|
197
203
|
# Advanced features
|
198
204
|
ruby examples/advanced/hash_expansion.rb
|
199
205
|
|
200
|
-
# Real-world scenarios
|
206
|
+
# Real-world scenarios
|
201
207
|
ruby examples/real_world/microservices_audit.rb
|
202
208
|
```
|
data/examples/basic_usage.rb
CHANGED
@@ -11,11 +11,11 @@ puts "=" * 30
|
|
11
11
|
class User
|
12
12
|
ROLE = "user"
|
13
13
|
MAX_LOGIN_ATTEMPTS = 3
|
14
|
-
|
14
|
+
|
15
15
|
def self.permissions
|
16
16
|
["read"]
|
17
17
|
end
|
18
|
-
|
18
|
+
|
19
19
|
def self.session_timeout
|
20
20
|
3600
|
21
21
|
end
|
@@ -24,11 +24,11 @@ end
|
|
24
24
|
class Admin
|
25
25
|
ROLE = "admin"
|
26
26
|
MAX_LOGIN_ATTEMPTS = 5
|
27
|
-
|
27
|
+
|
28
28
|
def self.permissions
|
29
29
|
["read", "write", "admin"]
|
30
30
|
end
|
31
|
-
|
31
|
+
|
32
32
|
def self.session_timeout
|
33
33
|
7200
|
34
34
|
end
|
@@ -40,33 +40,33 @@ classes = [User, Admin]
|
|
40
40
|
puts "\n1. Constants Comparison"
|
41
41
|
puts "-" * 25
|
42
42
|
result = ClassMetrix.extract(:constants)
|
43
|
-
|
44
|
-
|
43
|
+
.from(classes)
|
44
|
+
.to_markdown
|
45
45
|
puts result
|
46
46
|
|
47
47
|
# 2. Extract class methods
|
48
|
-
puts "\n2. Class Methods Comparison"
|
48
|
+
puts "\n2. Class Methods Comparison"
|
49
49
|
puts "-" * 25
|
50
50
|
result = ClassMetrix.extract(:class_methods)
|
51
|
-
|
52
|
-
|
51
|
+
.from(classes)
|
52
|
+
.to_markdown
|
53
53
|
puts result
|
54
54
|
|
55
55
|
# 3. Combined extraction
|
56
56
|
puts "\n3. Combined Analysis"
|
57
57
|
puts "-" * 25
|
58
58
|
result = ClassMetrix.extract(:constants, :class_methods)
|
59
|
-
|
60
|
-
|
59
|
+
.from(classes)
|
60
|
+
.to_markdown
|
61
61
|
puts result
|
62
62
|
|
63
63
|
# 4. Filtered analysis
|
64
64
|
puts "\n4. Filtered Analysis (ROLE and permissions only)"
|
65
65
|
puts "-" * 25
|
66
66
|
result = ClassMetrix.extract(:constants, :class_methods)
|
67
|
-
|
68
|
-
|
69
|
-
|
67
|
+
.from(classes)
|
68
|
+
.filter(/ROLE|permissions/)
|
69
|
+
.to_markdown
|
70
70
|
puts result
|
71
71
|
|
72
72
|
# 5. Hash expansion
|
@@ -75,14 +75,14 @@ puts "-" * 25
|
|
75
75
|
|
76
76
|
class ConfigExample
|
77
77
|
SETTINGS = { timeout: 30, retries: 3, ssl: true }.freeze
|
78
|
-
|
78
|
+
|
79
79
|
def self.database_config
|
80
80
|
{ host: "localhost", port: 5432, pool_size: 5 }
|
81
81
|
end
|
82
82
|
end
|
83
83
|
|
84
84
|
result = ClassMetrix.extract(:constants, :class_methods)
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
puts result
|
85
|
+
.from([ConfigExample])
|
86
|
+
.expand_hashes
|
87
|
+
.to_markdown
|
88
|
+
puts result
|
@@ -9,7 +9,7 @@ require_relative '../lib/class_metrix'
|
|
9
9
|
# Example classes
|
10
10
|
class ServiceA
|
11
11
|
CONFIG = { host: 'localhost', port: 3000, timeout: 30 }
|
12
|
-
|
12
|
+
|
13
13
|
def self.get_settings
|
14
14
|
{ cache: true, retries: 3 }
|
15
15
|
end
|
@@ -17,7 +17,7 @@ end
|
|
17
17
|
|
18
18
|
class ServiceB
|
19
19
|
CONFIG = { host: 'remote', port: 8080 }
|
20
|
-
|
20
|
+
|
21
21
|
def self.get_settings
|
22
22
|
{ cache: false, retries: 1 }
|
23
23
|
end
|
@@ -30,36 +30,35 @@ puts
|
|
30
30
|
levels = [:basic, :detailed, :verbose]
|
31
31
|
|
32
32
|
levels.each do |level|
|
33
|
-
puts "\n" + "="*50
|
33
|
+
puts "\n" + "=" * 50
|
34
34
|
puts "DEBUG LEVEL: #{level.upcase}"
|
35
|
-
puts "="*50
|
36
|
-
|
35
|
+
puts "=" * 50
|
36
|
+
|
37
37
|
begin
|
38
38
|
result = ClassMetrix.extract(:constants, :class_methods)
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
39
|
+
.from([ServiceA, ServiceB])
|
40
|
+
.expand_hashes
|
41
|
+
.debug(level) # Set debug level
|
42
|
+
.to_markdown
|
43
|
+
|
44
44
|
puts "\n--- Result Summary ---"
|
45
45
|
puts "Report generated successfully! ✅"
|
46
46
|
puts "Lines in output: #{result.lines.count}"
|
47
|
-
|
48
47
|
rescue => e
|
49
48
|
puts "Error: #{e.class}: #{e.message}"
|
50
49
|
end
|
51
|
-
|
50
|
+
|
52
51
|
puts "\n"
|
53
52
|
end
|
54
53
|
|
55
|
-
puts "\n" + "="*50
|
54
|
+
puts "\n" + "=" * 50
|
56
55
|
puts "DEBUG LEVEL SUMMARY"
|
57
|
-
puts "="*50
|
56
|
+
puts "=" * 50
|
58
57
|
puts
|
59
58
|
puts ":basic - Key decisions and summaries only"
|
60
|
-
puts ":detailed - More context and intermediate steps"
|
59
|
+
puts ":detailed - More context and intermediate steps"
|
61
60
|
puts ":verbose - Full details including individual value processing"
|
62
61
|
puts
|
63
62
|
puts "Use :basic for general troubleshooting"
|
64
63
|
puts "Use :detailed for understanding data flow"
|
65
|
-
puts "Use :verbose for deep debugging of specific values"
|
64
|
+
puts "Use :verbose for deep debugging of specific values"
|
data/examples/debug_mode_demo.rb
CHANGED
@@ -9,7 +9,7 @@ require_relative '../lib/class_metrix'
|
|
9
9
|
# Example classes with different types of values
|
10
10
|
class SafeService
|
11
11
|
CONFIG = { host: 'localhost', port: 3000 }
|
12
|
-
|
12
|
+
|
13
13
|
def self.timeout_config
|
14
14
|
{ connect: 30, read: 60 }
|
15
15
|
end
|
@@ -18,7 +18,7 @@ end
|
|
18
18
|
class ProblematicService
|
19
19
|
# This constant is a Class object (not a Hash)
|
20
20
|
CONFIG_CLASS = SafeService
|
21
|
-
|
21
|
+
|
22
22
|
def self.service_config
|
23
23
|
SafeService::CONFIG
|
24
24
|
end
|
@@ -29,11 +29,11 @@ class ProblematicObject
|
|
29
29
|
def inspect
|
30
30
|
raise "Inspect not allowed!"
|
31
31
|
end
|
32
|
-
|
32
|
+
|
33
33
|
def to_s
|
34
34
|
raise "To_s not allowed!"
|
35
35
|
end
|
36
|
-
|
36
|
+
|
37
37
|
def class
|
38
38
|
raise "Class not allowed!"
|
39
39
|
end
|
@@ -41,7 +41,7 @@ end
|
|
41
41
|
|
42
42
|
class WeirdService
|
43
43
|
BROKEN_OBJECT = ProblematicObject.new
|
44
|
-
|
44
|
+
|
45
45
|
def self.get_config
|
46
46
|
{ normal: 'value', broken: ProblematicObject.new }
|
47
47
|
end
|
@@ -58,18 +58,17 @@ puts
|
|
58
58
|
|
59
59
|
begin
|
60
60
|
result = ClassMetrix.extract(:constants, :class_methods)
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
61
|
+
.from([SafeService, ProblematicService, WeirdService])
|
62
|
+
.expand_hashes
|
63
|
+
.handle_errors
|
64
|
+
.debug # Enable debug mode
|
65
|
+
.to_markdown
|
66
|
+
|
67
67
|
puts "\n=== Generated Report ==="
|
68
68
|
puts result[0..500] + "..." if result.length > 500
|
69
69
|
puts "\nReport generated successfully! ✅"
|
70
70
|
puts "Note: Debug output above shows how problematic objects were handled safely."
|
71
|
-
|
72
71
|
rescue => e
|
73
72
|
puts "Error: #{e.class}: #{e.message}"
|
74
73
|
puts "This should not happen with the safety improvements!"
|
75
|
-
end
|
74
|
+
end
|