eager_eye 1.2.12 → 1.2.13
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/README.md +14 -2
- data/lib/eager_eye/fixers/add_includes.rb +62 -0
- data/lib/eager_eye/fixers/count_to_size.rb +24 -0
- data/lib/eager_eye/version.rb +1 -1
- metadata +4 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: c9b4195fa833057ee04ef87d148e78de8463fdbca97e234ba9d5b08ecaab9afc
|
|
4
|
+
data.tar.gz: f5c45a109aba0f563866669c4b6a32ce0823990fe5de467d65f6baea8d405197
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 8312903e2476381ad7d9fe8a5a22feb74eb97937c5d488efc96448df9b0f5973f9d612c35cccd5235900e2eb25011694c862bb1a45a5bdeb70b2a8e17be155e2
|
|
7
|
+
data.tar.gz: cc7b4336007a72b0d4131b311a2897d4dae9cf0b4ba18ceb4826f25931875f418067bd5a16e6d1fec472cbb29abd7d1f2d2f0b58cc943b871fdea4e9991fa623
|
data/README.md
CHANGED
|
@@ -57,7 +57,8 @@
|
|
|
57
57
|
|
|
58
58
|
🔧 **Developer-friendly:**
|
|
59
59
|
- Inline suppression (like RuboCop)
|
|
60
|
-
- Auto-fix support (
|
|
60
|
+
- Auto-fix support (3 fixers: PluckToSelect, CountToSize, AddIncludes)
|
|
61
|
+
- `.jbuilder` file support (`json.array!` iteration detection)
|
|
61
62
|
- JSON/Console output formats
|
|
62
63
|
- RSpec integration
|
|
63
64
|
|
|
@@ -524,6 +525,8 @@ eager_eye --fix --force
|
|
|
524
525
|
| Issue | Fix |
|
|
525
526
|
|-------|-----|
|
|
526
527
|
| `.pluck(:id)` inline | → `.select(:id)` |
|
|
528
|
+
| `.count` in iteration | → `.size` |
|
|
529
|
+
| Missing `includes` before loop | → `.includes(:assoc)` inserted |
|
|
527
530
|
|
|
528
531
|
### Example
|
|
529
532
|
|
|
@@ -535,6 +538,15 @@ app/services/user_service.rb:
|
|
|
535
538
|
- Post.where(user_id: User.active.pluck(:id))
|
|
536
539
|
+ Post.where(user_id: User.active.select(:id))
|
|
537
540
|
|
|
541
|
+
app/controllers/posts_controller.rb:
|
|
542
|
+
Line 8:
|
|
543
|
+
- user.posts.count
|
|
544
|
+
+ user.posts.size
|
|
545
|
+
|
|
546
|
+
Line 5:
|
|
547
|
+
- @posts.each do |post|
|
|
548
|
+
+ @posts.includes(:author).each do |post|
|
|
549
|
+
|
|
538
550
|
$ eager_eye --fix
|
|
539
551
|
app/services/user_service.rb:12
|
|
540
552
|
- Post.where(user_id: User.active.pluck(:id))
|
|
@@ -739,7 +751,7 @@ EagerEye uses static analysis, which means:
|
|
|
739
751
|
- **No runtime context** - Cannot know if associations are already eager loaded elsewhere
|
|
740
752
|
- **Heuristic-based** - Uses naming conventions to identify associations (may have false positives)
|
|
741
753
|
- **Ruby code only** - Does not analyze SQL queries or ActiveRecord internals
|
|
742
|
-
- **Cross-file scope** - Cross-file analysis
|
|
754
|
+
- **Cross-file scope** - Cross-file analysis covers model-defined query methods; controller-to-view or service-to-service patterns are not yet tracked
|
|
743
755
|
|
|
744
756
|
For best results, use EagerEye alongside runtime tools like Bullet for comprehensive N+1 detection.
|
|
745
757
|
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module EagerEye
|
|
4
|
+
module Fixers
|
|
5
|
+
class AddIncludes < Base
|
|
6
|
+
ITERATION_METHODS_RE = %w[
|
|
7
|
+
each map collect select find_all reject filter filter_map
|
|
8
|
+
flat_map find_each find_in_batches in_batches
|
|
9
|
+
].join("|")
|
|
10
|
+
ITERATION_PATTERN = /\.(#{ITERATION_METHODS_RE})\b/
|
|
11
|
+
|
|
12
|
+
def fixable?
|
|
13
|
+
issue.detector == :loop_association &&
|
|
14
|
+
!association_name.nil? &&
|
|
15
|
+
!iteration_line_index.nil?
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def diff
|
|
19
|
+
return nil unless fixable?
|
|
20
|
+
|
|
21
|
+
idx = iteration_line_index
|
|
22
|
+
original_line = @source_lines[idx]
|
|
23
|
+
fixed_line = insert_includes(original_line)
|
|
24
|
+
return nil if original_line == fixed_line
|
|
25
|
+
|
|
26
|
+
{
|
|
27
|
+
file: issue.file_path,
|
|
28
|
+
line: idx + 1,
|
|
29
|
+
original: original_line.chomp,
|
|
30
|
+
fixed: fixed_line.chomp
|
|
31
|
+
}
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
protected
|
|
35
|
+
|
|
36
|
+
def fixed_content
|
|
37
|
+
raise NotImplementedError
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
private
|
|
41
|
+
|
|
42
|
+
def association_name
|
|
43
|
+
return nil unless issue.suggestion
|
|
44
|
+
|
|
45
|
+
match = issue.suggestion.match(/includes\(:(\w+)\)/)
|
|
46
|
+
match && match[1]
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def iteration_line_index
|
|
50
|
+
start = issue.line_number - 2
|
|
51
|
+
start.downto([start - 10, 0].max) do |i|
|
|
52
|
+
return i if @source_lines[i]&.match?(ITERATION_PATTERN)
|
|
53
|
+
end
|
|
54
|
+
nil
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def insert_includes(line)
|
|
58
|
+
line.sub(ITERATION_PATTERN, ".includes(:#{association_name})\\0")
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module EagerEye
|
|
4
|
+
module Fixers
|
|
5
|
+
class CountToSize < Base
|
|
6
|
+
def fixable?
|
|
7
|
+
issue.detector == :count_in_iteration &&
|
|
8
|
+
single_line_count?
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
protected
|
|
12
|
+
|
|
13
|
+
def fixed_content
|
|
14
|
+
line_content.sub(/\.count\b/, ".size")
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
private
|
|
18
|
+
|
|
19
|
+
def single_line_count?
|
|
20
|
+
line_content&.match?(/\.count\b/)
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
data/lib/eager_eye/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: eager_eye
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.2.
|
|
4
|
+
version: 1.2.13
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- hamzagedikkaya
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-03-
|
|
11
|
+
date: 2026-03-23 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: ast
|
|
@@ -80,7 +80,9 @@ files:
|
|
|
80
80
|
- lib/eager_eye/detectors/serializer_nesting.rb
|
|
81
81
|
- lib/eager_eye/detectors/validation_n_plus_one.rb
|
|
82
82
|
- lib/eager_eye/fixer_registry.rb
|
|
83
|
+
- lib/eager_eye/fixers/add_includes.rb
|
|
83
84
|
- lib/eager_eye/fixers/base.rb
|
|
85
|
+
- lib/eager_eye/fixers/count_to_size.rb
|
|
84
86
|
- lib/eager_eye/fixers/pluck_to_select.rb
|
|
85
87
|
- lib/eager_eye/generators/install_generator.rb
|
|
86
88
|
- lib/eager_eye/issue.rb
|