bulletmark_repairer 0.1.4 → 0.1.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +8 -0
- data/README.md +3 -3
- data/lib/bulletmark_repairer/associations_builder.rb +11 -4
- data/lib/bulletmark_repairer/loaded_associations.rb +61 -0
- data/lib/bulletmark_repairer/monkey_patches/active_record/query_method.rb +22 -0
- data/lib/bulletmark_repairer/patcher.rb +4 -4
- data/lib/bulletmark_repairer/rack.rb +5 -3
- data/lib/bulletmark_repairer/railtie.rb +5 -0
- data/lib/bulletmark_repairer/thread.rb +30 -0
- data/lib/bulletmark_repairer/version.rb +1 -1
- data/lib/bulletmark_repairer.rb +2 -0
- metadata +6 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5eabc96bcf1961f834090322c3b9a62173139f806513c5ec99d452f18a661c71
|
4
|
+
data.tar.gz: b55ab6f5adade690b6cb34ef92fc752bdfa697a3b8d7779d54150aaf4e1083bb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 714da7b74b7015194f965c83c1260d31b8a4f75b4f7a24b3038eac6c81ced4aa8a77a79abbe5a684a347093fbb00d0e9f1b05682729b96afe64ed2a83b110534
|
7
|
+
data.tar.gz: e48064688caaa2003d30192bfd2a76ff677fdcb4b4bb02bb8b828fece22b9fd5dab69a47aef2fb836a69e9f5b16db10d2c1faefcb9e249ba5b8a3df671310c03
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,11 @@
|
|
1
|
+
## [0.1.6] - 2023-11-09
|
2
|
+
|
3
|
+
Fix a bug when N+1 is caused not in the request (e.g. Sidekiq) [51f051e](https://github.com/makicamel/bulletmark_repairer/commit/51f051e608b84b7da96ac879a324ed438c14eeeb)
|
4
|
+
|
5
|
+
## [0.1.5] - 2023-10-27
|
6
|
+
|
7
|
+
Be able to patch for nested associations require `includes` though child associations are already included [d1b7445](https://github.com/makicamel/bulletmark_repairer/commit/d1b7445556c20bc037beb6a013ac70531426a7ea)
|
8
|
+
|
1
9
|
## [0.1.4] - 2023-10-22
|
2
10
|
|
3
11
|
- Patch files other than controllers [218566d](https://github.com/makicamel/bulletmark_repairer/commit/218566d1531751f204941c3dcff7f095a056d39f)
|
data/README.md
CHANGED
@@ -47,12 +47,12 @@ For example, the following cases are not supported as known cases currently:
|
|
47
47
|
|
48
48
|
```ruby
|
49
49
|
def index
|
50
|
-
#
|
50
|
+
# Multiple nested associations require `includes` though child associations are already included
|
51
51
|
@plays = Play.includes(:actors)
|
52
52
|
# expected correct
|
53
|
-
@plays = Play.includes(actors:
|
53
|
+
@plays = Play.includes(:actors).includes({:actors=>{:company=>[:offices]}})
|
54
54
|
# actual correct
|
55
|
-
@plays = Play.includes(:actors).includes([:company])
|
55
|
+
@plays = Play.includes(:actors).includes({:actors=>[:company]})
|
56
56
|
end
|
57
57
|
```
|
58
58
|
|
@@ -10,7 +10,11 @@ module BulletmarkRepairer
|
|
10
10
|
if associations[marker.index]
|
11
11
|
associations[marker.index].add(marker)
|
12
12
|
else
|
13
|
-
associations[marker.index] = Associations.new(
|
13
|
+
associations[marker.index] = Associations.new(
|
14
|
+
marker,
|
15
|
+
@application_associations,
|
16
|
+
@loaded_associations
|
17
|
+
)
|
14
18
|
end
|
15
19
|
end
|
16
20
|
|
@@ -20,8 +24,9 @@ module BulletmarkRepairer
|
|
20
24
|
|
21
25
|
private
|
22
26
|
|
23
|
-
def initialize
|
27
|
+
def initialize(loaded_associations)
|
24
28
|
@application_associations = BulletmarkRepairer::ApplicationAssociations.new
|
29
|
+
@loaded_associations = BulletmarkRepairer::LoadedAssociations.new(loaded_associations)
|
25
30
|
end
|
26
31
|
end
|
27
32
|
|
@@ -44,10 +49,12 @@ module BulletmarkRepairer
|
|
44
49
|
|
45
50
|
private
|
46
51
|
|
47
|
-
def initialize(marker, application_associations)
|
52
|
+
def initialize(marker, application_associations, loaded_associations)
|
48
53
|
@marker = marker
|
49
|
-
@associations = { base: marker.associations }
|
50
54
|
@application_associations = application_associations
|
55
|
+
@loaded_associations = loaded_associations
|
56
|
+
key = @loaded_associations.key(marker.base_class)
|
57
|
+
@associations = { base: key ? { key => marker.associations } : marker.associations }
|
51
58
|
end
|
52
59
|
|
53
60
|
# @return [Hash, nil]
|
@@ -0,0 +1,61 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module BulletmarkRepairer
|
4
|
+
class LoadedAssociations
|
5
|
+
attr_reader :associations
|
6
|
+
|
7
|
+
def key(target_klass_name)
|
8
|
+
key = target_klass_name.underscore
|
9
|
+
|
10
|
+
result = []
|
11
|
+
@associations.each do |_base_klass_name, all_associations|
|
12
|
+
all_associations.each do |_key, associations|
|
13
|
+
# TODO: reccurent check
|
14
|
+
associations.each do |values|
|
15
|
+
values.flatten.each do |value|
|
16
|
+
result.append search_key(key, value)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
result = result.flatten.compact.uniq.presence
|
22
|
+
build_keys(result)
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def search_key(key, value)
|
28
|
+
case value
|
29
|
+
when Hash
|
30
|
+
search_key(key, value.keys) || search_key(key, value.values)
|
31
|
+
when Array
|
32
|
+
value.map { |v| search_key(key, v) }
|
33
|
+
else
|
34
|
+
if key.pluralize.to_sym == value
|
35
|
+
key.pluralize.to_sym
|
36
|
+
elsif key.singularize.to_sym == value
|
37
|
+
key.singularize.to_sym
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def build_keys(keys)
|
43
|
+
return unless keys
|
44
|
+
|
45
|
+
if keys.size == 1
|
46
|
+
keys.first
|
47
|
+
else
|
48
|
+
{ keys.first => keys.last }
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def initialize(original_associations)
|
53
|
+
@associations = Hash.new { |h, k| h[k] = {} }
|
54
|
+
original_associations.each do |base_class, all_associations|
|
55
|
+
all_associations.each do |key, associations|
|
56
|
+
@associations[base_class][key] = associations.to_a
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module BulletmarkRepairer
|
4
|
+
module ActiveRecord
|
5
|
+
module QueryMethod
|
6
|
+
def includes(*args)
|
7
|
+
BulletmarkRepairer::Thread.add(name: model.name, method_type: :includes, args: args)
|
8
|
+
super(args)
|
9
|
+
end
|
10
|
+
|
11
|
+
def eager_load(*args)
|
12
|
+
BulletmarkRepairer::Thread.add(name: model.name, method_type: :eager_load, args: args)
|
13
|
+
super(args)
|
14
|
+
end
|
15
|
+
|
16
|
+
def preload(*args)
|
17
|
+
BulletmarkRepairer::Thread.add(name: model.name, method_type: :preload, args: args)
|
18
|
+
super(args)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -6,8 +6,8 @@ require 'parser/runner/ruby_rewrite'
|
|
6
6
|
|
7
7
|
module BulletmarkRepairer
|
8
8
|
class Patcher
|
9
|
-
def self.execute(notifications:, controller:, action:)
|
10
|
-
new(notifications: notifications, controller: controller, action: action).execute
|
9
|
+
def self.execute(notifications:, controller:, action:, loaded_associations:)
|
10
|
+
new(notifications: notifications, controller: controller, action: action, loaded_associations: loaded_associations).execute
|
11
11
|
end
|
12
12
|
|
13
13
|
def execute
|
@@ -24,9 +24,9 @@ module BulletmarkRepairer
|
|
24
24
|
|
25
25
|
private
|
26
26
|
|
27
|
-
def initialize(notifications:, controller:, action:)
|
27
|
+
def initialize(notifications:, controller:, action:, loaded_associations:)
|
28
28
|
@markers = Markers.new(notifications, controller: controller, action: action)
|
29
|
-
@associations_builder = BulletmarkRepairer::AssociationsBuilder.new
|
29
|
+
@associations_builder = BulletmarkRepairer::AssociationsBuilder.new(loaded_associations)
|
30
30
|
end
|
31
31
|
end
|
32
32
|
end
|
@@ -10,16 +10,18 @@ module BulletmarkRepairer
|
|
10
10
|
@app.call(env)
|
11
11
|
ensure
|
12
12
|
begin
|
13
|
-
if Thread.current[:bullet_notification_collector].notifications_present?
|
13
|
+
if ::Thread.current[:bullet_notification_collector].notifications_present?
|
14
14
|
BulletmarkRepairer::Patcher.execute(
|
15
|
-
notifications: Thread.current[:bullet_notification_collector],
|
15
|
+
notifications: ::Thread.current[:bullet_notification_collector],
|
16
16
|
controller: env['action_dispatch.request.parameters']['controller'],
|
17
|
-
action: env['action_dispatch.request.parameters']['action']
|
17
|
+
action: env['action_dispatch.request.parameters']['action'],
|
18
|
+
loaded_associations: BulletmarkRepairer::Thread.current
|
18
19
|
)
|
19
20
|
end
|
20
21
|
rescue StandardError => e
|
21
22
|
raise e if BulletmarkRepairer.config.debug?
|
22
23
|
end
|
24
|
+
BulletmarkRepairer::Thread.clear
|
23
25
|
end
|
24
26
|
end
|
25
27
|
end
|
@@ -9,5 +9,10 @@ module BulletmarkRepairer
|
|
9
9
|
require 'bulletmark_repairer/rack'
|
10
10
|
app.middleware.insert_after Bullet::Rack, BulletmarkRepairer::Rack
|
11
11
|
end
|
12
|
+
|
13
|
+
ActiveSupport.on_load(:active_record) do
|
14
|
+
require 'bulletmark_repairer/monkey_patches/active_record/query_method'
|
15
|
+
::ActiveRecord::Relation.prepend(BulletmarkRepairer::ActiveRecord::QueryMethod)
|
16
|
+
end
|
12
17
|
end
|
13
18
|
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'rails'
|
4
|
+
|
5
|
+
module BulletmarkRepairer
|
6
|
+
class Thread
|
7
|
+
class << self
|
8
|
+
def current
|
9
|
+
touch
|
10
|
+
end
|
11
|
+
|
12
|
+
def add(name:, method_type:, args:)
|
13
|
+
touch
|
14
|
+
::Thread.current[:bulletmark_repaier_loaded_associations][name][method_type].add(args)
|
15
|
+
end
|
16
|
+
|
17
|
+
def clear
|
18
|
+
::Thread.current[:bulletmark_repaier_loaded_associations] = nil
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def touch
|
24
|
+
::Thread.current[:bulletmark_repaier_loaded_associations] ||= Hash.new do |hash, key|
|
25
|
+
hash[key] = { includes: Set.new, eager_load: Set.new, preload: Set.new }
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
data/lib/bulletmark_repairer.rb
CHANGED
@@ -6,8 +6,10 @@ require 'bulletmark_repairer/application_associations'
|
|
6
6
|
require 'bulletmark_repairer/associations_builder'
|
7
7
|
require 'bulletmark_repairer/configuration'
|
8
8
|
require 'bulletmark_repairer/corrector_builder'
|
9
|
+
require 'bulletmark_repairer/loaded_associations'
|
9
10
|
require 'bulletmark_repairer/markers'
|
10
11
|
require 'bulletmark_repairer/patcher'
|
12
|
+
require 'bulletmark_repairer/thread'
|
11
13
|
|
12
14
|
module BulletmarkRepairer
|
13
15
|
class Error < StandardError; end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bulletmark_repairer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- makicamel
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-11-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -88,11 +88,14 @@ files:
|
|
88
88
|
- lib/bulletmark_repairer/configuration.rb
|
89
89
|
- lib/bulletmark_repairer/controller_corrector.rb
|
90
90
|
- lib/bulletmark_repairer/corrector_builder.rb
|
91
|
+
- lib/bulletmark_repairer/loaded_associations.rb
|
91
92
|
- lib/bulletmark_repairer/markers.rb
|
93
|
+
- lib/bulletmark_repairer/monkey_patches/active_record/query_method.rb
|
92
94
|
- lib/bulletmark_repairer/patcher.rb
|
93
95
|
- lib/bulletmark_repairer/rack.rb
|
94
96
|
- lib/bulletmark_repairer/railtie.rb
|
95
97
|
- lib/bulletmark_repairer/retry_corrector.rb
|
98
|
+
- lib/bulletmark_repairer/thread.rb
|
96
99
|
- lib/bulletmark_repairer/version.rb
|
97
100
|
- sig/bulletmark_repairer.rbs
|
98
101
|
homepage: https://github.com/makicamel/bulletmark_repairer
|
@@ -118,7 +121,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
118
121
|
- !ruby/object:Gem::Version
|
119
122
|
version: '0'
|
120
123
|
requirements: []
|
121
|
-
rubygems_version: 3.4
|
124
|
+
rubygems_version: 3.1.4
|
122
125
|
signing_key:
|
123
126
|
specification_version: 4
|
124
127
|
summary: Auto corrector for N+1 queries detected at runtime with Bullet
|