rails_lens 0.2.4 → 0.2.6
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/CHANGELOG.md +14 -0
- data/README.md +3 -4
- data/lib/rails_lens/analyzers/association_analyzer.rb +2 -2
- data/lib/rails_lens/analyzers/composite_keys.rb +4 -4
- data/lib/rails_lens/analyzers/database_constraints.rb +2 -2
- data/lib/rails_lens/analyzers/delegated_types.rb +4 -4
- data/lib/rails_lens/analyzers/generated_columns.rb +2 -2
- data/lib/rails_lens/analyzers/inheritance.rb +10 -10
- data/lib/rails_lens/analyzers/notes.rb +10 -10
- data/lib/rails_lens/cli.rb +1 -1
- data/lib/rails_lens/cli_error_handler.rb +1 -1
- data/lib/rails_lens/configuration.rb +93 -0
- data/lib/rails_lens/erd/visualizer.rb +11 -11
- data/lib/rails_lens/errors.rb +2 -2
- data/lib/rails_lens/extension_loader.rb +2 -10
- data/lib/rails_lens/extensions/base.rb +2 -10
- data/lib/rails_lens/model_detector.rb +178 -58
- data/lib/rails_lens/providers/schema_provider.rb +6 -2
- data/lib/rails_lens/schema/adapters/mysql.rb +13 -13
- data/lib/rails_lens/schema/adapters/postgresql.rb +7 -7
- data/lib/rails_lens/schema/adapters/sqlite3.rb +5 -5
- data/lib/rails_lens/schema/annotation_manager.rb +112 -11
- data/lib/rails_lens/tasks/schema.rake +8 -1
- data/lib/rails_lens/version.rb +1 -1
- data/lib/rails_lens.rb +29 -79
- metadata +2 -1
@@ -85,8 +85,33 @@ module RailsLens
|
|
85
85
|
end
|
86
86
|
end
|
87
87
|
else
|
88
|
-
#
|
89
|
-
|
88
|
+
# Fallback: Use the model's connection pool with proper management
|
89
|
+
# This path is used when annotating individual models
|
90
|
+
warn "Using fallback connection management for #{model_class.name}" if RailsLens.config.verbose
|
91
|
+
|
92
|
+
# Force connection management even in fallback mode
|
93
|
+
results = { schema: nil, sections: [], notes: [] }
|
94
|
+
|
95
|
+
model_class.connection_pool.with_connection do |connection|
|
96
|
+
pipeline.instance_variable_get(:@providers).each do |provider|
|
97
|
+
next unless provider.applicable?(model_class)
|
98
|
+
|
99
|
+
begin
|
100
|
+
result = provider.process(model_class, connection)
|
101
|
+
|
102
|
+
case provider.type
|
103
|
+
when :schema
|
104
|
+
results[:schema] = result
|
105
|
+
when :section
|
106
|
+
results[:sections] << result if result
|
107
|
+
when :notes
|
108
|
+
results[:notes].concat(Array(result))
|
109
|
+
end
|
110
|
+
rescue StandardError => e
|
111
|
+
warn "Provider #{provider.class} error for #{model_class}: #{e.message}"
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
90
115
|
end
|
91
116
|
|
92
117
|
annotation = Annotation.new
|
@@ -117,7 +142,13 @@ module RailsLens
|
|
117
142
|
end
|
118
143
|
|
119
144
|
def self.annotate_all(options = {})
|
145
|
+
# Convert models option to include option for ModelDetector
|
146
|
+
if options[:models]
|
147
|
+
options[:include] = options[:models]
|
148
|
+
end
|
149
|
+
|
120
150
|
models = ModelDetector.detect_models(options)
|
151
|
+
puts "Detected #{models.size} models for annotation" if options[:verbose]
|
121
152
|
|
122
153
|
# Filter abstract classes based on options
|
123
154
|
if options[:include_abstract]
|
@@ -133,13 +164,35 @@ module RailsLens
|
|
133
164
|
|
134
165
|
# Group models by their connection pool to process each database separately
|
135
166
|
models_by_connection_pool = models.group_by do |model|
|
136
|
-
model.connection_pool
|
137
|
-
|
138
|
-
|
167
|
+
pool = model.connection_pool
|
168
|
+
pool
|
169
|
+
rescue StandardError => e
|
170
|
+
puts "Model #{model.name} -> NO POOL (#{e.message})" if options[:verbose]
|
171
|
+
nil # Models without connection pools will use primary pool
|
139
172
|
end
|
140
173
|
|
174
|
+
# Force models without connection pools to use the primary connection pool
|
175
|
+
if models_by_connection_pool[nil]&.any?
|
176
|
+
begin
|
177
|
+
primary_pool = ApplicationRecord.connection_pool
|
178
|
+
models_by_connection_pool[primary_pool] ||= []
|
179
|
+
models_by_connection_pool[primary_pool].concat(models_by_connection_pool[nil])
|
180
|
+
models_by_connection_pool.delete(nil)
|
181
|
+
rescue StandardError => e
|
182
|
+
puts "Failed to assign to primary pool: #{e.message}" if options[:verbose]
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
# Get all connection pools first
|
187
|
+
all_pools = get_all_connection_pools(models_by_connection_pool)
|
188
|
+
|
189
|
+
# Log initial connection status (removed verbose output)
|
190
|
+
|
141
191
|
models_by_connection_pool.each do |connection_pool, pool_models|
|
142
192
|
if connection_pool
|
193
|
+
# Disconnect all OTHER connection pools before processing this one
|
194
|
+
disconnect_other_pools(connection_pool, all_pools, options)
|
195
|
+
|
143
196
|
# Process all models for this database using a single connection
|
144
197
|
connection_pool.with_connection do |connection|
|
145
198
|
pool_models.each do |model|
|
@@ -147,9 +200,20 @@ module RailsLens
|
|
147
200
|
end
|
148
201
|
end
|
149
202
|
else
|
150
|
-
#
|
151
|
-
|
152
|
-
|
203
|
+
# This should not happen anymore since we assign orphaned models to primary pool
|
204
|
+
# Use primary connection pool as fallback to avoid creating new connections
|
205
|
+
begin
|
206
|
+
primary_pool = ApplicationRecord.connection_pool
|
207
|
+
primary_pool.with_connection do |connection|
|
208
|
+
pool_models.each do |model|
|
209
|
+
process_model_with_connection(model, connection, results, options)
|
210
|
+
end
|
211
|
+
end
|
212
|
+
rescue StandardError => e
|
213
|
+
# Last resort: process without connection management (will create multiple connections)
|
214
|
+
pool_models.each do |model|
|
215
|
+
process_model_with_connection(model, nil, results, options)
|
216
|
+
end
|
153
217
|
end
|
154
218
|
end
|
155
219
|
end
|
@@ -167,7 +231,6 @@ module RailsLens
|
|
167
231
|
# Skip models without tables or with missing tables (but not abstract classes)
|
168
232
|
unless model.abstract_class? || model.table_exists?
|
169
233
|
results[:skipped] << model.name
|
170
|
-
warn "Skipping #{model.name} - table does not exist" if options[:verbose]
|
171
234
|
return
|
172
235
|
end
|
173
236
|
|
@@ -191,10 +254,9 @@ module RailsLens
|
|
191
254
|
else
|
192
255
|
results[:skipped] << model.name
|
193
256
|
end
|
194
|
-
rescue ActiveRecord::StatementInvalid
|
257
|
+
rescue ActiveRecord::StatementInvalid
|
195
258
|
# Handle database-related errors (missing tables, schemas, etc.)
|
196
259
|
results[:skipped] << model.name
|
197
|
-
warn "Skipping #{model.name} - database error: #{e.message}" if options[:verbose]
|
198
260
|
rescue StandardError => e
|
199
261
|
model_name = if model.is_a?(Class) && model.respond_to?(:name)
|
200
262
|
model.name
|
@@ -222,6 +284,45 @@ module RailsLens
|
|
222
284
|
results
|
223
285
|
end
|
224
286
|
|
287
|
+
def self.disconnect_other_pools(current_pool, all_pools, options = {})
|
288
|
+
all_pools.each do |pool|
|
289
|
+
next if pool == current_pool || pool.nil?
|
290
|
+
|
291
|
+
begin
|
292
|
+
if pool.connected?
|
293
|
+
pool.disconnect!
|
294
|
+
end
|
295
|
+
rescue StandardError => e
|
296
|
+
warn "Failed to disconnect pool: #{e.message}"
|
297
|
+
end
|
298
|
+
end
|
299
|
+
end
|
300
|
+
|
301
|
+
def self.get_all_connection_pools(models_by_pool)
|
302
|
+
models_by_pool.keys.compact
|
303
|
+
end
|
304
|
+
|
305
|
+
def self.log_connection_status(all_pools, options = {})
|
306
|
+
return unless options[:verbose]
|
307
|
+
|
308
|
+
puts "\n=== Connection Pool Status ==="
|
309
|
+
all_pools.each do |pool|
|
310
|
+
next unless pool
|
311
|
+
|
312
|
+
begin
|
313
|
+
name = pool.db_config&.name || 'unknown'
|
314
|
+
connected = pool.connected?
|
315
|
+
size = pool.size
|
316
|
+
checked_out = pool.stat[:busy]
|
317
|
+
|
318
|
+
puts "Pool #{name}: connected=#{connected}, size=#{size}, busy=#{checked_out}"
|
319
|
+
rescue StandardError => e
|
320
|
+
puts "Pool status error: #{e.message}"
|
321
|
+
end
|
322
|
+
end
|
323
|
+
puts "================================\n"
|
324
|
+
end
|
325
|
+
|
225
326
|
private
|
226
327
|
|
227
328
|
def add_annotation(content, _file_path = nil)
|
@@ -9,7 +9,14 @@ namespace :rails_lens do
|
|
9
9
|
options = {}
|
10
10
|
options[:include_abstract] = true if ENV['INCLUDE_ABSTRACT'] == 'true'
|
11
11
|
|
12
|
-
|
12
|
+
# Support model filtering via environment variable
|
13
|
+
if ENV['MODELS']
|
14
|
+
model_list = ENV['MODELS'].split(',').map(&:strip)
|
15
|
+
options[:models] = model_list
|
16
|
+
puts "Filtering to specific models: #{model_list.join(', ')}"
|
17
|
+
end
|
18
|
+
|
19
|
+
options[:verbose] = true # Force verbose mode to see connection management
|
13
20
|
results = RailsLens.annotate_models(options)
|
14
21
|
|
15
22
|
if results[:annotated].any?
|
data/lib/rails_lens/version.rb
CHANGED
data/lib/rails_lens.rb
CHANGED
@@ -26,92 +26,31 @@ loader.setup
|
|
26
26
|
|
27
27
|
require_relative 'rails_lens/errors'
|
28
28
|
require_relative 'rails_lens/cli'
|
29
|
+
require_relative 'rails_lens/configuration'
|
29
30
|
|
30
31
|
module RailsLens
|
31
32
|
include ActiveSupport::Configurable
|
33
|
+
include Configuration
|
32
34
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
# Configuration using ActiveSupport::Configurable
|
39
|
-
config_accessor :annotations do
|
40
|
-
{
|
41
|
-
position: :before,
|
42
|
-
format: :rdoc
|
43
|
-
}
|
44
|
-
end
|
45
|
-
|
46
|
-
config_accessor :erd do
|
47
|
-
{
|
48
|
-
output_dir: 'doc/erd',
|
49
|
-
orientation: 'TB',
|
50
|
-
theme: true,
|
51
|
-
default_colors: %w[
|
52
|
-
lightblue
|
53
|
-
lightcoral
|
54
|
-
lightgreen
|
55
|
-
lightyellow
|
56
|
-
plum
|
57
|
-
lightcyan
|
58
|
-
lightgray
|
59
|
-
]
|
60
|
-
}
|
61
|
-
end
|
62
|
-
|
63
|
-
config_accessor :schema do
|
64
|
-
{
|
65
|
-
adapter: :auto,
|
66
|
-
include_notes: true,
|
67
|
-
exclude_tables: %w[schema_migrations ar_internal_metadata],
|
68
|
-
format_options: {
|
69
|
-
show_defaults: true,
|
70
|
-
show_comments: true,
|
71
|
-
show_foreign_keys: true,
|
72
|
-
show_indexes: true,
|
73
|
-
show_check_constraints: true
|
74
|
-
}
|
75
|
-
}
|
76
|
-
end
|
77
|
-
|
78
|
-
config_accessor :extensions do
|
79
|
-
{
|
80
|
-
enabled: true,
|
81
|
-
autoload: true,
|
82
|
-
interface_version: '1.0',
|
83
|
-
ignore: [],
|
84
|
-
custom_paths: [],
|
85
|
-
error_reporting: :warn, # :silent, :warn, :verbose
|
86
|
-
fail_safe_mode: true, # Continue processing if extensions fail
|
87
|
-
track_health: false # Track extension success/failure rates
|
88
|
-
}
|
89
|
-
end
|
35
|
+
class << self
|
36
|
+
def logger
|
37
|
+
@logger ||= config.logger || default_logger
|
38
|
+
end
|
90
39
|
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
include_constraints: true,
|
96
|
-
pattern: '**/*_controller.rb',
|
97
|
-
exclusion_pattern: 'vendor/**/*_controller.rb'
|
98
|
-
}
|
99
|
-
end
|
40
|
+
def logger=(new_logger)
|
41
|
+
@logger = new_logger
|
42
|
+
config.logger = new_logger
|
43
|
+
end
|
100
44
|
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
pattern: '**/*_mailer.rb',
|
110
|
-
exclusion_pattern: 'vendor/**/*_mailer.rb'
|
111
|
-
}
|
112
|
-
end
|
45
|
+
def default_logger
|
46
|
+
if defined?(Rails.logger) && Rails.logger
|
47
|
+
Rails.logger
|
48
|
+
else
|
49
|
+
require 'logger'
|
50
|
+
Logger.new($stdout)
|
51
|
+
end
|
52
|
+
end
|
113
53
|
|
114
|
-
class << self
|
115
54
|
def load_config_file(path = '.rails-lens.yml')
|
116
55
|
return unless File.exist?(path)
|
117
56
|
|
@@ -130,6 +69,17 @@ module RailsLens
|
|
130
69
|
end
|
131
70
|
end
|
132
71
|
|
72
|
+
# Get tables to exclude
|
73
|
+
def excluded_tables
|
74
|
+
custom_excludes = config.schema[:exclude_tables]
|
75
|
+
if custom_excludes.nil?
|
76
|
+
# Use ActiveRecord's default ignore tables
|
77
|
+
ActiveRecord::SchemaDumper.ignore_tables.to_a
|
78
|
+
else
|
79
|
+
Array(custom_excludes)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
133
83
|
# Schema annotation methods
|
134
84
|
def annotate_models(options = {})
|
135
85
|
Schema::AnnotationManager.annotate_all(options)
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rails_lens
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Abdelkader Boudih
|
@@ -182,6 +182,7 @@ files:
|
|
182
182
|
- lib/rails_lens/cli.rb
|
183
183
|
- lib/rails_lens/cli_error_handler.rb
|
184
184
|
- lib/rails_lens/commands.rb
|
185
|
+
- lib/rails_lens/configuration.rb
|
185
186
|
- lib/rails_lens/connection.rb
|
186
187
|
- lib/rails_lens/erd/column_type_formatter.rb
|
187
188
|
- lib/rails_lens/erd/domain_color_mapper.rb
|