diff --git a/lib/bullet.rb b/lib/bullet.rb index 58849986..026175a7 100644 --- a/lib/bullet.rb +++ b/lib/bullet.rb @@ -148,42 +148,47 @@ def debug(title, message) end def start_request - Thread.current[:bullet_start] = true - Thread.current[:bullet_notification_collector] = Bullet::NotificationCollector.new - - Thread.current[:bullet_object_associations] = Bullet::Registry::Base.new - Thread.current[:bullet_call_object_associations] = Bullet::Registry::Base.new - Thread.current[:bullet_possible_objects] = Bullet::Registry::Object.new - Thread.current[:bullet_impossible_objects] = Bullet::Registry::Object.new - Thread.current[:bullet_inversed_objects] = Bullet::Registry::Base.new - Thread.current[:bullet_eager_loadings] = Bullet::Registry::Association.new - Thread.current[:bullet_call_stacks] = Bullet::Registry::CallStack.new + Thread.current.thread_variable_set(:bullet_start, true) + Thread.current.thread_variable_set(:bullet_notification_collector, Bullet::NotificationCollector.new) + + Thread.current.thread_variable_set(:bullet_object_associations, Bullet::Registry::Base.new) + Thread.current.thread_variable_set(:bullet_call_object_associations, Bullet::Registry::Base.new) + Thread.current.thread_variable_set(:bullet_possible_objects, Bullet::Registry::Object.new) + Thread.current.thread_variable_set(:bullet_impossible_objects, Bullet::Registry::Object.new) + Thread.current.thread_variable_set(:bullet_inversed_objects, Bullet::Registry::Base.new) + Thread.current.thread_variable_set(:bullet_eager_loadings, Bullet::Registry::Association.new) + Thread.current.thread_variable_set(:bullet_call_stacks, Bullet::Registry::CallStack.new) + + unless Thread.current.thread_variable_get(:bullet_counter_possible_objects) + Thread.current.thread_variable_set(:bullet_counter_possible_objects, Bullet::Registry::Object.new) + end - Thread.current[:bullet_counter_possible_objects] ||= Bullet::Registry::Object.new - Thread.current[:bullet_counter_impossible_objects] ||= Bullet::Registry::Object.new + unless Thread.current.thread_variable_get(:bullet_counter_impossible_objects) + Thread.current.thread_variable_set(:bullet_counter_impossible_objects, Bullet::Registry::Object.new) + end end def end_request - Thread.current[:bullet_start] = nil - Thread.current[:bullet_notification_collector] = nil + Thread.current.thread_variable_set(:bullet_start, nil) + Thread.current.thread_variable_set(:bullet_notification_collector, nil) - Thread.current[:bullet_object_associations] = nil - Thread.current[:bullet_call_object_associations] = nil - Thread.current[:bullet_possible_objects] = nil - Thread.current[:bullet_impossible_objects] = nil - Thread.current[:bullet_inversed_objects] = nil - Thread.current[:bullet_eager_loadings] = nil + Thread.current.thread_variable_set(:bullet_object_associations, nil) + Thread.current.thread_variable_set(:bullet_call_object_associations, nil) + Thread.current.thread_variable_set(:bullet_possible_objects, nil) + Thread.current.thread_variable_set(:bullet_impossible_objects, nil) + Thread.current.thread_variable_set(:bullet_inversed_objects, nil) + Thread.current.thread_variable_set(:bullet_eager_loadings, nil) - Thread.current[:bullet_counter_possible_objects] = nil - Thread.current[:bullet_counter_impossible_objects] = nil + Thread.current.thread_variable_set(:bullet_counter_possible_objects, nil) + Thread.current.thread_variable_set(:bullet_counter_impossible_objects, nil) end def start? - enable? && Thread.current[:bullet_start] + enable? && Thread.current.thread_variable_get(:bullet_start) end def notification_collector - Thread.current[:bullet_notification_collector] + Thread.current.thread_variable_get(:bullet_notification_collector) end def notification? diff --git a/lib/bullet/detector/association.rb b/lib/bullet/detector/association.rb index 93cafe32..549ec039 100644 --- a/lib/bullet/detector/association.rb +++ b/lib/bullet/detector/association.rb @@ -34,7 +34,7 @@ def add_call_object_associations(object, associations) # that the objects may cause N+1 query. # e.g. { Post => ["Post:1", "Post:2"] } def possible_objects - Thread.current[:bullet_possible_objects] + Thread.current.thread_variable_get(:bullet_possible_objects) end # impossible_objects keep the class to objects relationships @@ -43,7 +43,7 @@ def possible_objects # if find collection returns only one object, then the object is impossible object, # impossible_objects are used to avoid treating 1+1 query to N+1 query. def impossible_objects - Thread.current[:bullet_impossible_objects] + Thread.current.thread_variable_get(:bullet_impossible_objects) end private @@ -54,7 +54,7 @@ def impossible_objects # the object_associations keep all associations that may be or may no be # unpreload associations or unused preload associations. def object_associations - Thread.current[:bullet_object_associations] + Thread.current.thread_variable_get(:bullet_object_associations) end # call_object_associations keep the object relationships @@ -62,27 +62,27 @@ def object_associations # e.g. { "Post:1" => [:comments] } # they are used to detect unused preload associations. def call_object_associations - Thread.current[:bullet_call_object_associations] + Thread.current.thread_variable_get(:bullet_call_object_associations) end # inversed_objects keeps object relationships # that association is inversed. # e.g. { "Comment:1" => ["post"] } def inversed_objects - Thread.current[:bullet_inversed_objects] + Thread.current.thread_variable_get(:bullet_inversed_objects) end # eager_loadings keep the object relationships # that the associations are preloaded by find :include. # e.g. { ["Post:1", "Post:2"] => [:comments, :user] } def eager_loadings - Thread.current[:bullet_eager_loadings] + Thread.current.thread_variable_get(:bullet_eager_loadings) end # cal_stacks keeps stacktraces where querie-objects were called from. # e.g. { 'Object:111' => [SomeProject/app/controllers/...] } def call_stacks - Thread.current[:bullet_call_stacks] + Thread.current.thread_variable_get(:bullet_call_stacks) end end end diff --git a/lib/bullet/detector/counter_cache.rb b/lib/bullet/detector/counter_cache.rb index d4e57133..62744dd9 100644 --- a/lib/bullet/detector/counter_cache.rb +++ b/lib/bullet/detector/counter_cache.rb @@ -44,11 +44,11 @@ def conditions_met?(object, _associations) end def possible_objects - Thread.current[:bullet_counter_possible_objects] + Thread.current.thread_variable_get(:bullet_counter_possible_objects) end def impossible_objects - Thread.current[:bullet_counter_impossible_objects] + Thread.current.thread_variable_get(:bullet_counter_impossible_objects) end private diff --git a/spec/integration/active_record/association_spec.rb b/spec/integration/active_record/association_spec.rb index 2fc37851..210d3215 100644 --- a/spec/integration/active_record/association_spec.rb +++ b/spec/integration/active_record/association_spec.rb @@ -113,6 +113,20 @@ expect(Bullet::Detector::Association).to be_detecting_unpreloaded_association_for(Post, :comments) end + + context 'inside Fiber' do + it 'should detect non preload post => comments' do + fiber = Fiber.new do + Post.all.each { |post| post.comments.map(&:name) } + end + fiber.resume + + Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations + expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations + + expect(Bullet::Detector::Association).to be_detecting_unpreloaded_association_for(Post, :comments) + end + end end context 'category => posts => comments' do