rails_lens 0.5.0 → 0.5.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 +4 -4
- data/CHANGELOG.md +14 -0
- data/lib/rails_lens/analyzers/association_analyzer.rb +11 -1
- data/lib/rails_lens/analyzers/callbacks.rb +6 -6
- data/lib/rails_lens/analyzers/composite_keys.rb +1 -1
- data/lib/rails_lens/analyzers/generated_columns.rb +1 -1
- data/lib/rails_lens/analyzers/notes.rb +11 -2
- data/lib/rails_lens/schema/adapters/database_info.rb +2 -2
- data/lib/rails_lens/schema/adapters/mysql.rb +20 -20
- data/lib/rails_lens/schema/annotation_manager.rb +4 -2
- data/lib/rails_lens/tasks/annotate.rake +14 -2
- data/lib/rails_lens/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 5180524144ca10c72173e0410e924877e7de878379a7924a0931adba19be185b
|
|
4
|
+
data.tar.gz: 4b76f310866feb24bb206b9004a4091c78553c147e9e0114131a693eb1d78097
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 655c2c927177454346c7b0dae09c4faaed881e2df93941c27a29511ba2c48dd5e42742f426036c0187f60bfa631ec60941e0e00de8b26b91012ef6e6a4727a9f
|
|
7
|
+
data.tar.gz: b7d9465fdb5daa3ed000dbca03c673a39fc8c7141ccebeb3d7c050d478358b99ba25a95c1f425365472d75c1ed06cf1cc4e332f78e0015a1bd289bf8eb5beff9
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.5.2](https://github.com/seuros/rails_lens/compare/rails_lens/v0.5.1...rails_lens/v0.5.2) (2026-02-16)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Bug Fixes
|
|
7
|
+
|
|
8
|
+
* reduce INVERSE_OF false positives for vanilla associations ([#39](https://github.com/seuros/rails_lens/issues/39)) ([b209c2a](https://github.com/seuros/rails_lens/commit/b209c2a6b2a894193561e9aa30985c3043b40ac3))
|
|
9
|
+
|
|
10
|
+
## [0.5.1](https://github.com/seuros/rails_lens/compare/rails_lens/v0.5.0...rails_lens/v0.5.1) (2025-12-07)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
### Bug Fixes
|
|
14
|
+
|
|
15
|
+
* add by_source ([f6693f3](https://github.com/seuros/rails_lens/commit/f6693f384761de505eac0e525c7b70f4c053d14c))
|
|
16
|
+
|
|
3
17
|
## [0.5.0](https://github.com/seuros/rails_lens/compare/rails_lens/v0.3.0...rails_lens/v0.5.0) (2025-12-06)
|
|
4
18
|
|
|
5
19
|
|
|
@@ -42,7 +42,7 @@ module RailsLens
|
|
|
42
42
|
def associations_needing_inverse
|
|
43
43
|
all_associations.select do |association|
|
|
44
44
|
association.options[:inverse_of].nil? &&
|
|
45
|
-
|
|
45
|
+
needs_explicit_inverse_of?(association) &&
|
|
46
46
|
!association.polymorphic? &&
|
|
47
47
|
bidirectional_association?(association)
|
|
48
48
|
end
|
|
@@ -71,6 +71,16 @@ module RailsLens
|
|
|
71
71
|
false
|
|
72
72
|
end
|
|
73
73
|
|
|
74
|
+
def needs_explicit_inverse_of?(association)
|
|
75
|
+
# Rails can auto-infer inverse_of for vanilla associations
|
|
76
|
+
# Only require explicit inverse_of when using custom options
|
|
77
|
+
association.options[:class_name].present? ||
|
|
78
|
+
association.options[:foreign_key].present? ||
|
|
79
|
+
association.options[:as].present? ||
|
|
80
|
+
association.options[:source].present? ||
|
|
81
|
+
association.options[:through].present?
|
|
82
|
+
end
|
|
83
|
+
|
|
74
84
|
def should_have_counter_cache?(association)
|
|
75
85
|
return false unless association.macro == :belongs_to
|
|
76
86
|
|
|
@@ -116,23 +116,23 @@ module RailsLens
|
|
|
116
116
|
case filter
|
|
117
117
|
when Symbol
|
|
118
118
|
# Check if method is defined in the model class itself
|
|
119
|
-
return true if model_class.
|
|
120
|
-
return true if model_class.
|
|
119
|
+
return true if model_class.method_defined?(filter, false)
|
|
120
|
+
return true if model_class.private_method_defined?(filter, false)
|
|
121
121
|
|
|
122
122
|
# Check if defined in included concerns (non-Rails modules)
|
|
123
123
|
model_class.included_modules.each do |mod|
|
|
124
124
|
next if mod.name.nil?
|
|
125
125
|
next if mod.name.start_with?('ActiveRecord', 'ActiveModel', 'ActiveSupport')
|
|
126
126
|
|
|
127
|
-
return true if mod.
|
|
128
|
-
return true if mod.
|
|
127
|
+
return true if mod.method_defined?(filter, false)
|
|
128
|
+
return true if mod.private_method_defined?(filter, false)
|
|
129
129
|
end
|
|
130
130
|
|
|
131
131
|
# For STI: check parent classes up to (but not including) ActiveRecord::Base
|
|
132
132
|
klass = model_class.superclass
|
|
133
133
|
while klass && klass < ActiveRecord::Base
|
|
134
|
-
return true if klass.
|
|
135
|
-
return true if klass.
|
|
134
|
+
return true if klass.method_defined?(filter, false)
|
|
135
|
+
return true if klass.private_method_defined?(filter, false)
|
|
136
136
|
|
|
137
137
|
klass = klass.superclass
|
|
138
138
|
end
|
|
@@ -35,7 +35,7 @@ module RailsLens
|
|
|
35
35
|
|
|
36
36
|
def detect_composite_primary_key_from_db
|
|
37
37
|
# Query PostgreSQL system catalogs to find composite primary keys
|
|
38
|
-
sql =
|
|
38
|
+
sql = <<~SQL.squish
|
|
39
39
|
SELECT a.attname
|
|
40
40
|
FROM pg_index i
|
|
41
41
|
JOIN pg_attribute a ON a.attrelid = i.indrelid AND a.attnum = ANY(i.indkey)
|
|
@@ -312,8 +312,7 @@ module RailsLens
|
|
|
312
312
|
def associations_needing_inverse
|
|
313
313
|
associations.select do |association|
|
|
314
314
|
association.options[:inverse_of].nil? &&
|
|
315
|
-
|
|
316
|
-
!association.options[:as] &&
|
|
315
|
+
needs_explicit_inverse_of?(association) &&
|
|
317
316
|
association.macro != :has_and_belongs_to_many
|
|
318
317
|
end
|
|
319
318
|
end
|
|
@@ -418,6 +417,16 @@ module RailsLens
|
|
|
418
417
|
RailsLens.logger.debug { "Error checking view existence for #{view_name}: #{e.message}" }
|
|
419
418
|
false
|
|
420
419
|
end
|
|
420
|
+
|
|
421
|
+
def needs_explicit_inverse_of?(association)
|
|
422
|
+
# Rails can auto-infer inverse_of for vanilla associations
|
|
423
|
+
# Only require explicit inverse_of when using custom options
|
|
424
|
+
association.options[:class_name].present? ||
|
|
425
|
+
association.options[:foreign_key].present? ||
|
|
426
|
+
association.options[:as].present? ||
|
|
427
|
+
association.options[:source].present? ||
|
|
428
|
+
association.options[:through].present?
|
|
429
|
+
end
|
|
421
430
|
end
|
|
422
431
|
end
|
|
423
432
|
end
|
|
@@ -84,7 +84,7 @@ module RailsLens
|
|
|
84
84
|
def extensions
|
|
85
85
|
return [] unless adapter_name == 'PostgreSQL'
|
|
86
86
|
|
|
87
|
-
connection.select_all(
|
|
87
|
+
connection.select_all(<<~SQL.squish).to_a
|
|
88
88
|
SELECT extname as name, extversion as version
|
|
89
89
|
FROM pg_extension
|
|
90
90
|
WHERE extname NOT IN ('plpgsql')
|
|
@@ -97,7 +97,7 @@ module RailsLens
|
|
|
97
97
|
def schemas
|
|
98
98
|
return [] unless adapter_name == 'PostgreSQL'
|
|
99
99
|
|
|
100
|
-
connection.select_values(
|
|
100
|
+
connection.select_values(<<~SQL.squish)
|
|
101
101
|
SELECT schema_name
|
|
102
102
|
FROM information_schema.schemata
|
|
103
103
|
WHERE schema_name NOT IN ('pg_catalog', 'information_schema', 'pg_toast')
|
|
@@ -211,12 +211,12 @@ module RailsLens
|
|
|
211
211
|
def has_partitions?
|
|
212
212
|
return false unless connection.respond_to?(:execute)
|
|
213
213
|
|
|
214
|
-
result = connection.execute(
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
214
|
+
result = connection.execute(<<~SQL.squish)
|
|
215
|
+
SELECT COUNT(*) as count
|
|
216
|
+
FROM information_schema.partitions
|
|
217
|
+
WHERE table_schema = DATABASE()
|
|
218
|
+
AND table_name = '#{table_name}'
|
|
219
|
+
AND partition_name IS NOT NULL
|
|
220
220
|
SQL
|
|
221
221
|
|
|
222
222
|
count = if result.first.is_a?(Hash)
|
|
@@ -241,13 +241,13 @@ module RailsLens
|
|
|
241
241
|
def add_partitions(lines)
|
|
242
242
|
return unless connection.respond_to?(:execute)
|
|
243
243
|
|
|
244
|
-
partitions = connection.execute(
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
244
|
+
partitions = connection.execute(<<~SQL.squish)
|
|
245
|
+
SELECT partition_name, partition_expression, partition_description
|
|
246
|
+
FROM information_schema.partitions
|
|
247
|
+
WHERE table_schema = DATABASE()
|
|
248
|
+
AND table_name = '#{table_name}'
|
|
249
|
+
AND partition_name IS NOT NULL
|
|
250
|
+
ORDER BY partition_ordinal_position
|
|
251
251
|
SQL
|
|
252
252
|
|
|
253
253
|
return if partitions.none?
|
|
@@ -269,13 +269,13 @@ module RailsLens
|
|
|
269
269
|
def add_partitions_toml(lines)
|
|
270
270
|
return unless connection.respond_to?(:execute)
|
|
271
271
|
|
|
272
|
-
partitions = connection.execute(
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
272
|
+
partitions = connection.execute(<<~SQL.squish)
|
|
273
|
+
SELECT partition_name, partition_expression, partition_description
|
|
274
|
+
FROM information_schema.partitions
|
|
275
|
+
WHERE table_schema = DATABASE()
|
|
276
|
+
AND table_name = '#{table_name}'
|
|
277
|
+
AND partition_name IS NOT NULL
|
|
278
|
+
ORDER BY partition_ordinal_position
|
|
279
279
|
SQL
|
|
280
280
|
|
|
281
281
|
return if partitions.none?
|
|
@@ -148,12 +148,13 @@ module RailsLens
|
|
|
148
148
|
end
|
|
149
149
|
|
|
150
150
|
def self.annotate_all(options = {})
|
|
151
|
-
results = { annotated: [], skipped: [], failed: [] }
|
|
151
|
+
results = { annotated: [], skipped: [], failed: [], by_source: {} }
|
|
152
152
|
|
|
153
153
|
# Iterate through all model sources
|
|
154
154
|
ModelSourceLoader.load_sources.each do |source|
|
|
155
155
|
puts "Annotating #{source.source_name} models..." if options[:verbose]
|
|
156
156
|
source_results = annotate_source(source, options)
|
|
157
|
+
results[:by_source][source.source_name] = source_results[:annotated].length
|
|
157
158
|
merge_results(results, source_results)
|
|
158
159
|
end
|
|
159
160
|
|
|
@@ -312,12 +313,13 @@ module RailsLens
|
|
|
312
313
|
end
|
|
313
314
|
|
|
314
315
|
def self.remove_all(options = {})
|
|
315
|
-
results = { removed: [], skipped: [], failed: [] }
|
|
316
|
+
results = { removed: [], skipped: [], failed: [], by_source: {} }
|
|
316
317
|
|
|
317
318
|
# Iterate through all model sources
|
|
318
319
|
ModelSourceLoader.load_sources.each do |source|
|
|
319
320
|
puts "Removing annotations from #{source.source_name} models..." if options[:verbose]
|
|
320
321
|
source_results = remove_source(source, options)
|
|
322
|
+
results[:by_source][source.source_name] = source_results[:removed].length
|
|
321
323
|
merge_remove_results(results, source_results)
|
|
322
324
|
end
|
|
323
325
|
|
|
@@ -11,7 +11,13 @@ namespace :rails_lens do
|
|
|
11
11
|
|
|
12
12
|
results = RailsLens::Schema::AnnotationManager.annotate_all(options)
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
if results[:by_source]&.any?
|
|
15
|
+
results[:by_source].each do |source_name, count|
|
|
16
|
+
puts "Annotated #{count} #{source_name} models" if count.positive?
|
|
17
|
+
end
|
|
18
|
+
else
|
|
19
|
+
puts "Annotated #{results[:annotated].length} models"
|
|
20
|
+
end
|
|
15
21
|
puts "Skipped #{results[:skipped].length} models" if results[:skipped].any?
|
|
16
22
|
if results[:failed].any?
|
|
17
23
|
puts "Failed to annotate #{results[:failed].length} models:"
|
|
@@ -27,7 +33,13 @@ namespace :rails_lens do
|
|
|
27
33
|
|
|
28
34
|
results = RailsLens::Schema::AnnotationManager.remove_all
|
|
29
35
|
|
|
30
|
-
|
|
36
|
+
if results[:by_source]&.any?
|
|
37
|
+
results[:by_source].each do |source_name, count|
|
|
38
|
+
puts "Removed annotations from #{count} #{source_name} models" if count.positive?
|
|
39
|
+
end
|
|
40
|
+
elsif results[:removed].any?
|
|
41
|
+
puts "Removed annotations from #{results[:removed].length} models"
|
|
42
|
+
end
|
|
31
43
|
puts "Skipped #{results[:skipped].length} models (no annotations)" if results[:skipped].any?
|
|
32
44
|
if results[:failed].any?
|
|
33
45
|
puts "Failed to remove annotations from #{results[:failed].length} models:"
|
data/lib/rails_lens/version.rb
CHANGED
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.5.
|
|
4
|
+
version: 0.5.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Abdelkader Boudih
|
|
@@ -270,7 +270,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
270
270
|
- !ruby/object:Gem::Version
|
|
271
271
|
version: '0'
|
|
272
272
|
requirements: []
|
|
273
|
-
rubygems_version:
|
|
273
|
+
rubygems_version: 4.0.3
|
|
274
274
|
specification_version: 4
|
|
275
275
|
summary: Comprehensive Rails application visualization and annotation
|
|
276
276
|
test_files: []
|