rails_lens 0.10.0 → 0.10.1
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 +8 -0
- data/lib/rails_lens/analyzers/inheritance.rb +4 -5
- data/lib/rails_lens/analyzers/notes.rb +4 -2
- data/lib/rails_lens/cli.rb +2 -1
- data/lib/rails_lens/commands.rb +26 -17
- data/lib/rails_lens/model_detector.rb +3 -3
- data/lib/rails_lens/providers/extension_notes_provider.rb +2 -1
- data/lib/rails_lens/schema/adapters/base.rb +1 -0
- data/lib/rails_lens/schema/adapters/database_info.rb +9 -3
- data/lib/rails_lens/tasks/annotate.rake +20 -12
- data/lib/rails_lens/tasks/mailers.rake +2 -2
- data/lib/rails_lens/tasks/routes.rake +3 -2
- data/lib/rails_lens/tasks/schema.rake +11 -6
- data/lib/rails_lens/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: d3be7f4e3942405ae7fcd4d50998f62db251786490ebf01cf71637dd3715783a
|
|
4
|
+
data.tar.gz: 712440cb4e800e14b4c10739228144bcbf8308a79fb3b73593df8ccbb7e52b67
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 3bcbf3d18443edeb680ab8fa4fd7a3be4c4d95dcf47566c421fb8d0f57ff63deb7ec42d4bf8298154a77093d1b1385213c476a61d5b1b0c37ff2f33a2e867e9f
|
|
7
|
+
data.tar.gz: 1af1394845cc4c6db4e15b2004379100f959b073abee2efab52d77ce3c88ada3939e61e74f458f1e36e4eedd92bb93ef2b3fbb2b30c2ad972584bcaebb2553d2
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.10.1](https://github.com/seuros/rails_lens/compare/rails_lens/v0.10.0...rails_lens/v0.10.1) (2026-10-15)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Bug Fixes
|
|
7
|
+
|
|
8
|
+
* keep the WHERE clause of partial indexes in annotations ([#50](https://github.com/seuros/rails_lens/issues/50)) ([351476e](https://github.com/seuros/rails_lens/commit/351476e03d98e5fb0c506cf7c63e13680230a804))
|
|
9
|
+
* pluralize model/file counts in CLI and rake output ([#47](https://github.com/seuros/rails_lens/issues/47)) ([d870c6c](https://github.com/seuros/rails_lens/commit/d870c6c5128177a6324bc2db17f32be1538e73da))
|
|
10
|
+
|
|
3
11
|
## [0.10.0](https://github.com/seuros/rails_lens/compare/rails_lens/v0.5.4...rails_lens/v0.10.0) (2026-08-10)
|
|
4
12
|
|
|
5
13
|
|
|
@@ -162,11 +162,10 @@ module RailsLens
|
|
|
162
162
|
else
|
|
163
163
|
[]
|
|
164
164
|
end
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
end
|
|
165
|
+
fields = "name = \"#{reflection.name}\", type_col = \"#{reflection.foreign_type}\", " \
|
|
166
|
+
"id_col = \"#{reflection.foreign_key}\""
|
|
167
|
+
fields += ", types = #{TomlFormat.quoted_array(types)}" if types.any?
|
|
168
|
+
"{ #{fields} }"
|
|
170
169
|
end
|
|
171
170
|
lines << "references = [#{refs.join(', ')}]"
|
|
172
171
|
end
|
|
@@ -222,7 +222,8 @@ module RailsLens
|
|
|
222
222
|
end
|
|
223
223
|
|
|
224
224
|
# Check for STI without index
|
|
225
|
-
if model_class.inheritance_column && column_exists?(model_class.inheritance_column) &&
|
|
225
|
+
if model_class.inheritance_column && column_exists?(model_class.inheritance_column) &&
|
|
226
|
+
!has_index?(model_class.inheritance_column)
|
|
226
227
|
notes << NoteCodes.note(model_class.inheritance_column, NoteCodes::STI_INDEX)
|
|
227
228
|
end
|
|
228
229
|
|
|
@@ -327,7 +328,8 @@ module RailsLens
|
|
|
327
328
|
def associations_needing_counter_cache
|
|
328
329
|
belongs_to_associations.select do |association|
|
|
329
330
|
# Check if the inverse association exists and is commonly counted
|
|
330
|
-
|
|
331
|
+
inverse_name = association.inverse_of&.name || model_class.name.underscore.pluralize
|
|
332
|
+
inverse = association.klass.reflect_on_association(inverse_name)
|
|
331
333
|
inverse && inverse.macro == :has_many && !association.options[:counter_cache]
|
|
332
334
|
rescue NameError => e
|
|
333
335
|
RailsLens.logger.debug { "Failed to check counter cache for association: #{e.message}" }
|
data/lib/rails_lens/cli.rb
CHANGED
|
@@ -21,7 +21,8 @@ module RailsLens
|
|
|
21
21
|
desc 'annotate', 'Annotate Rails models with schema information'
|
|
22
22
|
option :models, type: :array, desc: 'Specific models to annotate'
|
|
23
23
|
option :include_abstract, type: :boolean, desc: 'Include abstract classes'
|
|
24
|
-
option :include_database_objects, type: :boolean, default: true,
|
|
24
|
+
option :include_database_objects, type: :boolean, default: true,
|
|
25
|
+
desc: 'Include database objects (functions, etc.) in abstract classes'
|
|
25
26
|
option :position, type: :string, enum: %w[before after top bottom], desc: 'Annotation position'
|
|
26
27
|
option :routes, type: :boolean, desc: 'Annotate controller routes'
|
|
27
28
|
option :mailers, type: :boolean, desc: 'Annotate mailer methods'
|
data/lib/rails_lens/commands.rb
CHANGED
|
@@ -14,8 +14,8 @@ module RailsLens
|
|
|
14
14
|
def annotate_models(options = {})
|
|
15
15
|
results = Schema::AnnotationManager.annotate_all(options)
|
|
16
16
|
|
|
17
|
-
output.say "Annotated #{results[:annotated]
|
|
18
|
-
report_skipped_and_failed(results, '
|
|
17
|
+
output.say "Annotated #{count_of(results[:annotated], 'model')}", :green
|
|
18
|
+
report_skipped_and_failed(results, 'model')
|
|
19
19
|
|
|
20
20
|
# Also annotate database-level objects (functions, etc.)
|
|
21
21
|
if options[:include_database_objects]
|
|
@@ -29,32 +29,33 @@ module RailsLens
|
|
|
29
29
|
def annotate_database_objects(options = {})
|
|
30
30
|
results = Schema::DatabaseAnnotator.annotate_all(options)
|
|
31
31
|
|
|
32
|
-
output.say "Annotated #{results[:annotated]
|
|
33
|
-
report_skipped_and_failed(results, 'abstract
|
|
32
|
+
output.say "Annotated #{count_of(results[:annotated], 'abstract base class')} with database objects", :green
|
|
33
|
+
report_skipped_and_failed(results, 'abstract class')
|
|
34
34
|
|
|
35
35
|
results
|
|
36
36
|
end
|
|
37
37
|
|
|
38
38
|
def annotate_routes(options = {})
|
|
39
|
-
annotate_files(Route::Annotator.new(dry_run: options[:dry_run]), 'controller
|
|
39
|
+
annotate_files(Route::Annotator.new(dry_run: options[:dry_run]), 'controller file', options,
|
|
40
|
+
suffix: 'with routes')
|
|
40
41
|
end
|
|
41
42
|
|
|
42
43
|
def annotate_mailers(options = {})
|
|
43
|
-
annotate_files(Mailer::Annotator.new(dry_run: options[:dry_run]), 'mailer
|
|
44
|
+
annotate_files(Mailer::Annotator.new(dry_run: options[:dry_run]), 'mailer file', options)
|
|
44
45
|
end
|
|
45
46
|
|
|
46
47
|
def remove_models(options = {})
|
|
47
48
|
results = Schema::AnnotationManager.remove_all(options)
|
|
48
|
-
output.say "Removed annotations from #{results[:removed]
|
|
49
|
+
output.say "Removed annotations from #{count_of(results[:removed], 'model')}", :green
|
|
49
50
|
results
|
|
50
51
|
end
|
|
51
52
|
|
|
52
53
|
def remove_routes(options = {})
|
|
53
|
-
remove_files(Route::Annotator.new(dry_run: options[:dry_run]), 'route', 'controller
|
|
54
|
+
remove_files(Route::Annotator.new(dry_run: options[:dry_run]), 'route', 'controller file')
|
|
54
55
|
end
|
|
55
56
|
|
|
56
57
|
def remove_mailers(options = {})
|
|
57
|
-
remove_files(Mailer::Annotator.new(dry_run: options[:dry_run]), 'mailer', 'mailer
|
|
58
|
+
remove_files(Mailer::Annotator.new(dry_run: options[:dry_run]), 'mailer', 'mailer file')
|
|
58
59
|
end
|
|
59
60
|
|
|
60
61
|
def generate_erd(options = {})
|
|
@@ -195,27 +196,33 @@ module RailsLens
|
|
|
195
196
|
|
|
196
197
|
private
|
|
197
198
|
|
|
199
|
+
# "1 model" / "0 models" — count plus the correctly inflected noun.
|
|
200
|
+
def count_of(countable, singular)
|
|
201
|
+
count = countable.respond_to?(:length) ? countable.length : countable
|
|
202
|
+
"#{count} #{singular.pluralize(count)}"
|
|
203
|
+
end
|
|
204
|
+
|
|
198
205
|
# Report skipped/failed counts for a model-annotation results hash.
|
|
199
206
|
def report_skipped_and_failed(results, noun)
|
|
200
|
-
output.say "Skipped #{results[:skipped]
|
|
207
|
+
output.say "Skipped #{count_of(results[:skipped], noun)}", :yellow if results[:skipped].any?
|
|
201
208
|
return unless results[:failed].any?
|
|
202
209
|
|
|
203
|
-
output.say "Failed to annotate #{results[:failed]
|
|
210
|
+
output.say "Failed to annotate #{count_of(results[:failed], noun)}:", :red
|
|
204
211
|
results[:failed].each do |failure|
|
|
205
212
|
output.say " - #{failure[:model]}: #{failure[:error]}", :red
|
|
206
213
|
end
|
|
207
214
|
end
|
|
208
215
|
|
|
209
|
-
def annotate_files(annotator,
|
|
216
|
+
def annotate_files(annotator, singular, options, suffix: nil)
|
|
210
217
|
changed_files = annotator.annotate_all
|
|
211
|
-
output.say "Annotated #{changed_files
|
|
218
|
+
output.say ["Annotated #{count_of(changed_files, singular)}", suffix].compact.join(' '), :green
|
|
212
219
|
changed_files.each { |file| output.say " - #{file}", :blue } if options[:verbose] && changed_files.any?
|
|
213
220
|
{ changed_files: changed_files }
|
|
214
221
|
end
|
|
215
222
|
|
|
216
|
-
def remove_files(annotator, kind,
|
|
223
|
+
def remove_files(annotator, kind, singular)
|
|
217
224
|
changed_files = annotator.remove_all
|
|
218
|
-
output.say "Removed #{kind} annotations from #{changed_files
|
|
225
|
+
output.say "Removed #{kind} annotations from #{count_of(changed_files, singular)}", :green
|
|
219
226
|
{ changed_files: changed_files }
|
|
220
227
|
end
|
|
221
228
|
|
|
@@ -255,8 +262,10 @@ module RailsLens
|
|
|
255
262
|
# Use RailsLens directly if available
|
|
256
263
|
if defined?(RailsLens)
|
|
257
264
|
results = RailsLens::Schema::AnnotationManager.annotate_all
|
|
258
|
-
|
|
259
|
-
|
|
265
|
+
annotated = results[:annotated].length
|
|
266
|
+
skipped = results[:skipped].length
|
|
267
|
+
puts "Rails Lens: Annotated \#{annotated} \#{'model'.pluralize(annotated)}"
|
|
268
|
+
puts "Rails Lens: Skipped \#{skipped} \#{'model'.pluralize(skipped)}" if skipped.positive?
|
|
260
269
|
else
|
|
261
270
|
# Fallback to CLI
|
|
262
271
|
system('bundle exec rails_lens annotate --quiet')
|
|
@@ -32,7 +32,9 @@ module RailsLens
|
|
|
32
32
|
end
|
|
33
33
|
|
|
34
34
|
def sti_child_models
|
|
35
|
-
concrete_models.select
|
|
35
|
+
concrete_models.select do |model|
|
|
36
|
+
model.superclass != ActiveRecord::Base && concrete_models.include?(model.superclass)
|
|
37
|
+
end
|
|
36
38
|
end
|
|
37
39
|
|
|
38
40
|
def view_backed_models
|
|
@@ -96,7 +98,6 @@ module RailsLens
|
|
|
96
98
|
false # If we can't check, assume it's not a view
|
|
97
99
|
end
|
|
98
100
|
|
|
99
|
-
# rubocop:disable Naming/PredicateMethod
|
|
100
101
|
def check_postgresql_view(connection, table_name)
|
|
101
102
|
# Handle schema-qualified table names (e.g., 'audit.audit_logs')
|
|
102
103
|
if table_name.include?('.')
|
|
@@ -153,7 +154,6 @@ module RailsLens
|
|
|
153
154
|
SQL
|
|
154
155
|
result.rows.any?
|
|
155
156
|
end
|
|
156
|
-
# rubocop:enable Naming/PredicateMethod
|
|
157
157
|
|
|
158
158
|
def eager_load_models
|
|
159
159
|
# Zeitwerk is always available in Rails 7+
|
|
@@ -9,7 +9,8 @@ module RailsLens
|
|
|
9
9
|
|
|
10
10
|
def applicable?(model_class)
|
|
11
11
|
# Only applicable to tables, not views
|
|
12
|
-
RailsLens.config.extensions[:enabled] && model_has_table?(model_class) &&
|
|
12
|
+
RailsLens.config.extensions[:enabled] && model_has_table?(model_class) &&
|
|
13
|
+
!ModelDetector.view_exists?(model_class)
|
|
13
14
|
end
|
|
14
15
|
|
|
15
16
|
def process(model_class, connection = nil)
|
|
@@ -337,6 +337,7 @@ module RailsLens
|
|
|
337
337
|
attrs << "columns = #{TomlFormat.quoted_array(Array(index.columns))}"
|
|
338
338
|
attrs << 'unique = true' if index.unique
|
|
339
339
|
attrs << "type = \"#{index.type}\"" if index.respond_to?(:type) && index.type
|
|
340
|
+
attrs << "where = \"#{index.where}\"" if index.respond_to?(:where) && index.where
|
|
340
341
|
line += attrs.join(', ')
|
|
341
342
|
line += ' }'
|
|
342
343
|
line += ',' if i < indexes.length - 1
|
|
@@ -62,9 +62,13 @@ module RailsLens
|
|
|
62
62
|
def database_encoding
|
|
63
63
|
case adapter_name
|
|
64
64
|
when 'PostgreSQL'
|
|
65
|
-
connection.select_value(
|
|
65
|
+
connection.select_value(
|
|
66
|
+
'SELECT pg_encoding_to_char(encoding) FROM pg_database WHERE datname = current_database()'
|
|
67
|
+
)
|
|
66
68
|
when 'Mysql2'
|
|
67
|
-
connection.select_value(
|
|
69
|
+
connection.select_value(
|
|
70
|
+
'SELECT DEFAULT_CHARACTER_SET_NAME FROM information_schema.SCHEMATA WHERE SCHEMA_NAME = DATABASE()'
|
|
71
|
+
)
|
|
68
72
|
end
|
|
69
73
|
rescue StandardError
|
|
70
74
|
nil
|
|
@@ -75,7 +79,9 @@ module RailsLens
|
|
|
75
79
|
when 'PostgreSQL'
|
|
76
80
|
connection.select_value('SELECT datcollate FROM pg_database WHERE datname = current_database()')
|
|
77
81
|
when 'Mysql2'
|
|
78
|
-
connection.select_value(
|
|
82
|
+
connection.select_value(
|
|
83
|
+
'SELECT DEFAULT_COLLATION_NAME FROM information_schema.SCHEMATA WHERE SCHEMA_NAME = DATABASE()'
|
|
84
|
+
)
|
|
79
85
|
end
|
|
80
86
|
rescue StandardError
|
|
81
87
|
nil
|
|
@@ -11,16 +11,20 @@ namespace :rails_lens do
|
|
|
11
11
|
|
|
12
12
|
results = RailsLens::Schema::AnnotationManager.annotate_all(options)
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
# Only report sources that actually produced annotations; a registered source with
|
|
15
|
+
# nothing to annotate is noise, not news.
|
|
16
|
+
annotated_by_source = (results[:by_source] || {}).select { |_source_name, count| count.positive? }
|
|
17
|
+
|
|
18
|
+
if annotated_by_source.any?
|
|
19
|
+
annotated_by_source.each do |source_name, count|
|
|
20
|
+
puts "Annotated #{count} #{source_name} #{'model'.pluralize(count)}"
|
|
17
21
|
end
|
|
18
22
|
else
|
|
19
|
-
puts "Annotated #{results[:annotated].length}
|
|
23
|
+
puts "Annotated #{results[:annotated].length} #{'model'.pluralize(results[:annotated].length)}"
|
|
20
24
|
end
|
|
21
|
-
puts "Skipped #{results[:skipped].length}
|
|
25
|
+
puts "Skipped #{results[:skipped].length} #{'model'.pluralize(results[:skipped].length)}" if results[:skipped].any?
|
|
22
26
|
if results[:failed].any?
|
|
23
|
-
puts "Failed to annotate #{results[:failed].length}
|
|
27
|
+
puts "Failed to annotate #{results[:failed].length} #{'model'.pluralize(results[:failed].length)}:"
|
|
24
28
|
results[:failed].each do |failure|
|
|
25
29
|
puts " - #{failure[:model]}: #{failure[:error]}"
|
|
26
30
|
end
|
|
@@ -38,16 +42,20 @@ namespace :rails_lens do
|
|
|
38
42
|
|
|
39
43
|
results = RailsLens::Schema::AnnotationManager.remove_all
|
|
40
44
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
45
|
+
removed_by_source = (results[:by_source] || {}).select { |_source_name, count| count.positive? }
|
|
46
|
+
|
|
47
|
+
if removed_by_source.any?
|
|
48
|
+
removed_by_source.each do |source_name, count|
|
|
49
|
+
puts "Removed annotations from #{count} #{source_name} #{'model'.pluralize(count)}"
|
|
44
50
|
end
|
|
45
51
|
elsif results[:removed].any?
|
|
46
|
-
puts "Removed annotations from #{results[:removed].length}
|
|
52
|
+
puts "Removed annotations from #{results[:removed].length} #{'model'.pluralize(results[:removed].length)}"
|
|
53
|
+
end
|
|
54
|
+
if results[:skipped].any?
|
|
55
|
+
puts "Skipped #{results[:skipped].length} #{'model'.pluralize(results[:skipped].length)} (no annotations)"
|
|
47
56
|
end
|
|
48
|
-
puts "Skipped #{results[:skipped].length} models (no annotations)" if results[:skipped].any?
|
|
49
57
|
if results[:failed].any?
|
|
50
|
-
puts "Failed to remove annotations from #{results[:failed].length}
|
|
58
|
+
puts "Failed to remove annotations from #{results[:failed].length} #{'model'.pluralize(results[:failed].length)}:"
|
|
51
59
|
results[:failed].each do |failure|
|
|
52
60
|
puts " - #{failure[:model]}: #{failure[:error]}"
|
|
53
61
|
end
|
|
@@ -9,7 +9,7 @@ namespace :rails_lens do
|
|
|
9
9
|
annotator = RailsLens::Mailer::Annotator.new
|
|
10
10
|
changed_files = annotator.annotate_all
|
|
11
11
|
|
|
12
|
-
puts "Annotated #{changed_files.length} mailer
|
|
12
|
+
puts "Annotated #{changed_files.length} #{'mailer file'.pluralize(changed_files.length)} with mailer information"
|
|
13
13
|
changed_files.each { |file| puts " - #{file}" }
|
|
14
14
|
end
|
|
15
15
|
|
|
@@ -20,7 +20,7 @@ namespace :rails_lens do
|
|
|
20
20
|
annotator = RailsLens::Mailer::Annotator.new
|
|
21
21
|
changed_files = annotator.remove_all
|
|
22
22
|
|
|
23
|
-
puts "Removed mailer annotations from #{changed_files.length} mailer
|
|
23
|
+
puts "Removed mailer annotations from #{changed_files.length} #{'mailer file'.pluralize(changed_files.length)}"
|
|
24
24
|
changed_files.each { |file| puts " - #{file}" }
|
|
25
25
|
end
|
|
26
26
|
end
|
|
@@ -9,7 +9,8 @@ namespace :rails_lens do
|
|
|
9
9
|
annotator = RailsLens::Route::Annotator.new
|
|
10
10
|
changed_files = annotator.annotate_all
|
|
11
11
|
|
|
12
|
-
puts "Annotated #{changed_files.length} controller
|
|
12
|
+
puts "Annotated #{changed_files.length} #{'controller file'.pluralize(changed_files.length)} " \
|
|
13
|
+
'with route information'
|
|
13
14
|
changed_files.each { |file| puts " - #{file}" }
|
|
14
15
|
end
|
|
15
16
|
|
|
@@ -20,7 +21,7 @@ namespace :rails_lens do
|
|
|
20
21
|
annotator = RailsLens::Route::Annotator.new
|
|
21
22
|
changed_files = annotator.remove_all
|
|
22
23
|
|
|
23
|
-
puts "Removed route annotations from #{changed_files.length} controller
|
|
24
|
+
puts "Removed route annotations from #{changed_files.length} #{'controller file'.pluralize(changed_files.length)}"
|
|
24
25
|
changed_files.each { |file| puts " - #{file}" }
|
|
25
26
|
end
|
|
26
27
|
end
|
|
@@ -20,14 +20,16 @@ namespace :rails_lens do
|
|
|
20
20
|
results = RailsLens.annotate_models(options)
|
|
21
21
|
|
|
22
22
|
if results[:annotated].any?
|
|
23
|
-
puts "Annotated #{results[:annotated].length}
|
|
23
|
+
puts "Annotated #{results[:annotated].length} #{'model'.pluralize(results[:annotated].length)}"
|
|
24
24
|
puts '(including abstract classes)' if options[:include_abstract]
|
|
25
25
|
end
|
|
26
26
|
|
|
27
|
-
|
|
27
|
+
if results[:skipped].any?
|
|
28
|
+
puts "\nSkipped #{results[:skipped].length} #{'model'.pluralize(results[:skipped].length)} (no changes needed)"
|
|
29
|
+
end
|
|
28
30
|
|
|
29
31
|
if results[:failed].any?
|
|
30
|
-
puts "\nFailed to annotate #{results[:failed].length}
|
|
32
|
+
puts "\nFailed to annotate #{results[:failed].length} #{'model'.pluralize(results[:failed].length)}:"
|
|
31
33
|
results[:failed].each do |failure|
|
|
32
34
|
puts " ✗ #{failure[:model]}: #{failure[:error]}"
|
|
33
35
|
end
|
|
@@ -42,14 +44,17 @@ namespace :rails_lens do
|
|
|
42
44
|
results = RailsLens.remove_annotations
|
|
43
45
|
|
|
44
46
|
if results[:removed].any?
|
|
45
|
-
puts "Removed annotations from #{results[:removed].length}
|
|
47
|
+
puts "Removed annotations from #{results[:removed].length} #{'model'.pluralize(results[:removed].length)}:"
|
|
46
48
|
results[:removed].each { |model| puts " ✓ #{model}" }
|
|
47
49
|
end
|
|
48
50
|
|
|
49
|
-
|
|
51
|
+
if results[:skipped].any?
|
|
52
|
+
puts "\nSkipped #{results[:skipped].length} #{'model'.pluralize(results[:skipped].length)} " \
|
|
53
|
+
'(no annotations found)'
|
|
54
|
+
end
|
|
50
55
|
|
|
51
56
|
if results[:failed].any?
|
|
52
|
-
puts "\nFailed to process #{results[:failed].length}
|
|
57
|
+
puts "\nFailed to process #{results[:failed].length} #{'model'.pluralize(results[:failed].length)}:"
|
|
53
58
|
results[:failed].each do |failure|
|
|
54
59
|
puts " ✗ #{failure[:model]}: #{failure[:error]}"
|
|
55
60
|
end
|
data/lib/rails_lens/version.rb
CHANGED