Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

use ar_key instead of AR object, move Bullet ext to spec/support/bull…

…et_ext, fix activerecord 3.1 extension
  • Loading branch information...
commit d8cdcf51b8ad4d5c50b3427ee60e7d38be31239a 1 parent 3e8b948
@flyerhzm authored
View
6 lib/bullet.rb
@@ -1,6 +1,12 @@
require 'set'
require 'uniform_notifier'
+class Object
+ def ar_key
+ "#{self.class}:#{self.id}"
+ end
+end
+
module Bullet
if Rails.version =~ /\A3\.0/
autoload :ActiveRecord, 'bullet/active_record3'
View
13 lib/bullet/active_record31.rb
@@ -69,13 +69,12 @@ def load_target
end
end
- ::ActiveRecord::Associations::Association.class_eval do
- # call has_one and belong_to association
- alias_method :origin_load_target, :load_target
- def load_target
- # avoid stack level too deep
- result = origin_load_target
- Bullet::Detector::NPlusOneQuery.call_association(@owner, @reflection.name) unless caller.any? {|c| c.include?("load_target") }
+ ::ActiveRecord::Associations::SingularAssociation.class_eval do
+ # call has_one and belongs_to associations
+ alias_method :origin_reader, :reader
+ def reader(force_reload = false)
+ result = origin_reader(force_reload)
+ Bullet::Detector::NPlusOneQuery.call_association(@owner, @reflection.name)
Bullet::Detector::Association.add_possible_objects(result)
result
end
View
30 lib/bullet/detector/association.rb
@@ -20,28 +20,30 @@ def clear
end
def add_object_associations(object, associations)
- object_associations.add(object, associations)
+ object_associations.add(object.ar_key, associations)
end
def add_call_object_associations(object, associations)
- call_object_associations.add(object, associations)
+ if object.id
+ call_object_associations.add(object.ar_key, associations)
+ end
end
def add_possible_objects(objects)
- possible_objects.add objects
+ possible_objects.add Array(objects).map(&:ar_key)
end
def add_impossible_object(object)
- impossible_objects.add object
+ impossible_objects.add object.ar_key
end
def add_eager_loadings(objects, associations)
- objects = Array(objects)
+ object_ar_keys = Array(objects).map(&:ar_key)
to_add = nil
to_merge, to_delete = [], []
eager_loadings.each do |k, v|
- key_objects_overlap = k & objects
+ key_objects_overlap = k & object_ar_keys
next if key_objects_overlap.empty?
@@ -51,10 +53,10 @@ def add_eager_loadings(objects, associations)
else
to_merge << [key_objects_overlap, ( eager_loadings[k].dup << associations )]
- keys_without_objects = k - objects
+ keys_without_objects = k - object_ar_keys
to_merge << [keys_without_objects, eager_loadings[k]]
to_delete << k
- objects = objects - k
+ object_ar_keys = object_ar_keys - k
end
end
@@ -62,13 +64,13 @@ def add_eager_loadings(objects, associations)
to_merge.each { |k,val| eager_loadings.merge k, val }
to_delete.each { |k| eager_loadings.delete k }
- eager_loadings.add objects, associations unless objects.empty?
+ eager_loadings.add object_ar_keys, associations unless object_ar_keys.empty?
end
private
# object_associations keep the object relationships
# that the object has many associations.
- # e.g. { <Post id:1> => [:comments] }
+ # e.g. { "Post:1" => [:comments] }
# the object_associations keep all associations that may be or may no be
# unpreload associations or unused preload associations.
def object_associations
@@ -77,7 +79,7 @@ def object_associations
# call_object_assciations keep the object relationships
# that object.associations is called.
- # e.g. { <Post id:1> => [:comments] }
+ # e.g. { "Post:1" => [:comments] }
# they are used to detect unused preload associations.
def call_object_associations
@@call_object_associations ||= Bullet::Registry::Base.new
@@ -85,14 +87,14 @@ def call_object_associations
# possible_objects keep the class to object relationships
# that the objects may cause N+1 query.
- # e.g. { Post => [<Post id:1>, <Post id:2>] }
+ # e.g. { Post => ["Post:1", "Post:2"] }
def possible_objects
@@possible_objects ||= Bullet::Registry::Object.new
end
# impossible_objects keep the class to objects relationships
# that the objects may not cause N+1 query.
- # e.g. { Post => [<Post id:1>, <Post id:2>] }
+ # e.g. { Post => ["Post:1", "Post:2"] }
# Notice: impossible_objects are not accurate,
# 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.
@@ -102,7 +104,7 @@ def impossible_objects
# eager_loadings keep the object relationships
# that the associations are preloaded by find :include.
- # e.g. { [<Post id:1>, <Post id:2>] => [:comments, :user] }
+ # e.g. { ["Post:1", "Post:2"] => [:comments, :user] }
def eager_loadings
@@eager_loadings ||= Bullet::Registry::Association.new
end
View
12 lib/bullet/detector/counter.rb
@@ -8,17 +8,17 @@ def clear
end
def add_counter_cache(object, associations)
- if conditions_met?(object, associations)
- create_notification object.class, associations
+ if conditions_met?(object.ar_key, associations)
+ create_notification object.class.to_s, associations
end
end
def add_possible_objects(objects)
- possible_objects.add objects
+ possible_objects.add Array(objects).map(&:ar_key)
end
def add_impossible_object(object)
- impossible_objects.add object
+ impossible_objects.add object.ar_key
end
private
@@ -35,8 +35,8 @@ def impossible_objects
@@impossible_objects ||= Bullet::Registry::Object.new
end
- def conditions_met?(object, associations)
- possible_objects.include?(object) && !impossible_objects.include?(object)
+ def conditions_met?(object_ar_key, associations)
+ possible_objects.include?(object_ar_key) && !impossible_objects.include?(object_ar_key)
end
end
end
View
20 lib/bullet/detector/n_plus_one_query.rb
@@ -10,8 +10,8 @@ def call_association(object, associations)
@@checked = true
add_call_object_associations(object, associations)
- if conditions_met?(object, associations)
- create_notification caller_in_project, object.class, associations
+ if conditions_met?(object.ar_key, associations)
+ create_notification caller_in_project, object.class.to_s, associations
end
end
@@ -22,8 +22,8 @@ def create_notification(callers, klazz, associations)
end
# decide whether the object.associations is unpreloaded or not.
- def conditions_met?(object, associations)
- possible?(object) && !impossible?(object) && !association?(object, associations)
+ def conditions_met?(object_ar_key, associations)
+ possible?(object_ar_key) && !impossible?(object_ar_key) && !association?(object_ar_key, associations)
end
def caller_in_project
@@ -31,17 +31,17 @@ def caller_in_project
caller.select { |c| c.include?(Rails.root) && !c.include?(vendor_root) }
end
- def possible?(object)
- possible_objects.include? object
+ def possible?(object_ar_key)
+ possible_objects.include? object_ar_key
end
- def impossible?(object)
- impossible_objects.include? object
+ def impossible?(object_ar_key)
+ impossible_objects.include? object_ar_key
end
# check if object => associations already exists in object_associations.
- def association?(object, associations)
- value = object_associations[object]
+ def association?(object_ar_key, associations)
+ value = object_associations[object_ar_key]
if value
value.each do |v|
result = v.is_a?(Hash) ? v.has_key?(associations) : v == associations
View
16 lib/bullet/detector/unused_eager_association.rb
@@ -8,11 +8,11 @@ class <<self
# if association not in call_object_association, then the object => association - call_object_association is ununsed preload assocations
def check_unused_preload_associations
@@checked = true
- object_associations.each do |object, association|
- object_association_diff = diff_object_association object, association
+ object_associations.each do |object_ar_key, association|
+ object_association_diff = diff_object_association object_ar_key, association
next if object_association_diff.empty?
- create_notification object.class, object_association_diff
+ create_notification object_ar_key.split(":").first, object_association_diff
end
end
@@ -22,18 +22,18 @@ def create_notification(klazz, associations)
Bullet.notification_collector.add(notice)
end
- def call_associations(object, association)
+ def call_associations(object_ar_key, association)
all = Set.new
- eager_loadings.similarly_associated(object, association).each do |related_object|
- coa = call_object_associations[related_object]
+ eager_loadings.similarly_associated(object_ar_key, association).each do |related_object_ar_key|
+ coa = call_object_associations[related_object_ar_key]
next if coa.nil?
all.merge coa
end
all.to_a
end
- def diff_object_association(object, association)
- potential_objects = association - call_associations(object, association)
+ def diff_object_association(object_ar_key, association)
+ potential_objects = association - call_associations(object_ar_key, association)
potential_objects.reject { |a| a.is_a?(Hash) }
end
end
View
11 lib/bullet/registry/object.rb
@@ -1,13 +1,14 @@
module Bullet
module Registry
class Object < Base
- def add(object_or_objects)
- klazz = object_or_objects.is_a?(Array) ? object_or_objects.first.class : object_or_objects.class
- super(klazz, object_or_objects)
+ def add(object_ar_keys)
+ klazz = Array(object_ar_keys).first.split(":").first
+ super(klazz, object_ar_keys)
end
- def include?(object)
- super(object.class, object)
+ def include?(object_ar_key)
+ klazz = object_ar_key.split(":").first
+ super(klazz, object_ar_key)
end
end
end
View
67 spec/bullet/detector/association_spec.rb
@@ -3,7 +3,11 @@
module Bullet
module Detector
describe Association do
- after(:each) { Association.clear }
+ before :all do
+ @post1 = Post.first
+ @post2 = Post.last
+ end
+ before(:each) { Association.clear }
context ".start_request" do
it "should set @@checked to false" do
@@ -25,71 +29,60 @@ module Detector
context ".add_object_association" do
it "should add object, associations pair" do
- object = Object.new
- Association.add_object_associations(object, :associations)
- Association.send(:object_associations).should be_include(object, :associations)
+ Association.add_object_associations(@post1, :associations)
+ Association.send(:object_associations).should be_include(@post1.ar_key, :associations)
end
end
context ".add_call_object_associations" do
it "should add call object, associations pair" do
- object = Object.new
- Association.add_call_object_associations(object, :associations)
- Association.send(:call_object_associations).should be_include(object, :associations)
+ Association.add_call_object_associations(@post1, :associations)
+ Association.send(:call_object_associations).should be_include(@post1.ar_key, :associations)
end
end
context ".add_possible_objects" do
it "should add possible objects" do
- object1 = Object.new
- object2 = Object.new
- Association.add_possible_objects([object1, object2])
- Association.send(:possible_objects).should be_include(object1)
- Association.send(:possible_objects).should be_include(object2)
+ Association.add_possible_objects([@post1, @post2])
+ Association.send(:possible_objects).should be_include(@post1.ar_key)
+ Association.send(:possible_objects).should be_include(@post2.ar_key)
end
end
context ".add_impossible_object" do
it "should add impossible object" do
- object = Object.new
- Association.add_impossible_object(object)
- Association.send(:impossible_objects).should be_include(object)
+ Association.add_impossible_object(@post1)
+ Association.send(:impossible_objects).should be_include(@post1.ar_key)
end
end
context ".add_eager_loadings" do
- before :each do
- @object1 = Object.new
- @object2 = Object.new
- Association.clear
- end
-
it "should add objects, associations pair when eager_loadings are empty" do
- Association.add_eager_loadings([@object1, @object2], :associations)
- Association.send(:eager_loadings).should be_include([@object1, @object2], :associations)
+ Association.add_eager_loadings([@post1, @post2], :associations)
+ Association.send(:eager_loadings).should be_include([@post1.ar_key, @post2.ar_key], :associations)
end
it "should add objects, associations pair for existing eager_loadings" do
- Association.add_eager_loadings([@object1, @object2], :association1)
- Association.add_eager_loadings([@object1, @object2], :association2)
- Association.send(:eager_loadings).should be_include([@object1, @object2], :association1)
- Association.send(:eager_loadings).should be_include([@object1, @object2], :association2)
+ Association.add_eager_loadings([@post1, @post2], :association1)
+ Association.add_eager_loadings([@post1, @post2], :association2)
+ Association.send(:eager_loadings).should be_include([@post1.ar_key, @post2.ar_key], :association1)
+ Association.send(:eager_loadings).should be_include([@post1.ar_key, @post2.ar_key], :association2)
end
it "should merge objects, associations pair for existing eager_loadings" do
- Association.add_eager_loadings(@object1, :association1)
- Association.add_eager_loadings([@object1, @object2], :association2)
- Association.send(:eager_loadings).should be_include([@object1], :association1)
- Association.send(:eager_loadings).should be_include([@object1], :association2)
- Association.send(:eager_loadings).should be_include([@object1, @object2], :association2)
+ Association.add_eager_loadings(@post1, :association1)
+ Association.add_eager_loadings([@post1, @post2], :association2)
+ Association.send(:eager_loadings).should be_include([@post1.ar_key], :association1)
+ Association.send(:eager_loadings).should be_include([@post1.ar_key], :association2)
+ Association.send(:eager_loadings).should be_include([@post1.ar_key, @post2.ar_key], :association2)
end
it "should delete objects, associations pair for existing eager_loadings" do
- Association.add_eager_loadings([@object1, @object2], :association1)
- Association.add_eager_loadings(@object1, :association2)
- Association.send(:eager_loadings).should be_include([@object1], :association1)
- Association.send(:eager_loadings).should be_include([@object1], :association2)
- Association.send(:eager_loadings).should be_include([@object2], :association1)
+ Association.add_eager_loadings([@post1, @post2], :association1)
+ Association.add_eager_loadings(@post1, :association2)
+ Association.send(:eager_loadings).should be_include([@post1.ar_key], :association1)
+ Association.send(:eager_loadings).should be_include([@post1.ar_key], :association2)
+ Association.send(:eager_loadings).should be_include([@post2.ar_key], :association1)
end
end
end
View
50 spec/bullet/detector/counter_spec.rb
@@ -3,7 +3,11 @@
module Bullet
module Detector
describe Counter do
- after(:each) { Counter.clear }
+ before :all do
+ @post1 = Post.first
+ @post2 = Post.last
+ end
+ before(:each) { Counter.clear }
context ".clear" do
it "should clear all class variables" do
@@ -13,39 +17,47 @@ module Detector
end
end
+ context ".add_counter_cache" do
+ it "should create notification if conditions met" do
+ Counter.should_receive(:conditions_met?).with(@post1.ar_key, [:comments]).and_return(true)
+ Counter.should_receive(:create_notification).with("Post", [:comments])
+ Counter.add_counter_cache(@post1, [:comments])
+ end
+
+ it "should not create notification if conditions not met" do
+ Counter.should_receive(:conditions_met?).with(@post1.ar_key, [:comments]).and_return(false)
+ Counter.should_receive(:create_notification).never
+ Counter.add_counter_cache(@post1, [:comments])
+ end
+ end
+
context ".add_possible_objects" do
it "should add possible objects" do
- object1 = Object.new
- object2 = Object.new
- Counter.add_possible_objects([object1, object2])
- Counter.send(:possible_objects).should be_include(object1)
- Counter.send(:possible_objects).should be_include(object2)
+ Counter.add_possible_objects([@post1, @post2])
+ Counter.send(:possible_objects).should be_include(@post1.ar_key)
+ Counter.send(:possible_objects).should be_include(@post2.ar_key)
end
it "should add impossible object" do
- object = Object.new
- Counter.add_impossible_object(object)
- Counter.send(:impossible_objects).should be_include(object)
+ Counter.add_impossible_object(@post1)
+ Counter.send(:impossible_objects).should be_include(@post1.ar_key)
end
end
context ".conditions_met?" do
it "should be true when object is possible, not impossible" do
- object = Object.new
- Counter.add_possible_objects(object)
- Counter.send(:conditions_met?, object, :associations).should be_true
+ Counter.add_possible_objects(@post1)
+ Counter.send(:conditions_met?, @post1.ar_key, :associations).should be_true
end
it "should be false when object is not possible" do
- object = Object.new
- Counter.send(:conditions_met?, object, :associations).should be_false
+ Counter.send(:conditions_met?, @post1.ar_key, :associations).should be_false
end
- it "should be true when object is possible, not impossible" do
- object = Object.new
- Counter.add_possible_objects(object)
- Counter.add_impossible_object(object)
- Counter.send(:conditions_met?, object, :associations).should be_false
+ it "should be true when object is possible, and impossible" do
+ Counter.add_possible_objects(@post1)
+ Counter.add_impossible_object(@post1)
+ Counter.send(:conditions_met?, @post1.ar_key, :associations).should be_false
end
end
end
View
70 spec/bullet/detector/n_plus_one_query_spec.rb
@@ -3,90 +3,90 @@
module Bullet
module Detector
describe NPlusOneQuery do
- before(:each) { @object = Object.new }
- after(:each) { NPlusOneQuery.clear }
+ before(:all) { @post = Post.first }
+ before(:each) { NPlusOneQuery.clear }
context ".call_association" do
it "should set @@checked to true" do
- NPlusOneQuery.call_association(@object, :associations)
+ NPlusOneQuery.call_association(@post, :associations)
NPlusOneQuery.class_variable_get(:@@checked).should be_true
end
it "should add call_object_associations" do
- NPlusOneQuery.should_receive(:add_call_object_associations).with(@object, :associations)
- NPlusOneQuery.call_association(@object, :associations)
+ NPlusOneQuery.should_receive(:add_call_object_associations).with(@post, :associations)
+ NPlusOneQuery.call_association(@post, :associations)
end
end
context ".possible?" do
it "should be true if possible_objects contain" do
- NPlusOneQuery.add_possible_objects(@object)
- NPlusOneQuery.send(:possible?, @object).should be_true
+ NPlusOneQuery.add_possible_objects(@post)
+ NPlusOneQuery.send(:possible?, @post.ar_key).should be_true
end
end
context ".impossible?" do
it "should be true if impossible_objects contain" do
- NPlusOneQuery.add_impossible_object(@object)
- NPlusOneQuery.send(:impossible?, @object).should be_true
+ NPlusOneQuery.add_impossible_object(@post)
+ NPlusOneQuery.send(:impossible?, @post.ar_key).should be_true
end
end
context ".association?" do
it "should be true if object, associations pair is already existed" do
- NPlusOneQuery.add_object_associations(@object, :association)
- NPlusOneQuery.send(:association?, @object, :association).should be_true
+ NPlusOneQuery.add_object_associations(@post, :association)
+ NPlusOneQuery.send(:association?, @post.ar_key, :association).should be_true
end
it "should be false if object, association pair is not existed" do
- NPlusOneQuery.add_object_associations(@object, :association1)
- NPlusOneQuery.send(:association?, @object, :associatio2).should be_false
+ NPlusOneQuery.add_object_associations(@post, :association1)
+ NPlusOneQuery.send(:association?, @post.ar_key, :associatio2).should be_false
end
end
context ".conditions_met?" do
it "should be true if object is possible, not impossible and object, associations pair is not already existed" do
- NPlusOneQuery.stub(:possible?).with(@object).and_return(true)
- NPlusOneQuery.stub(:impossible?).with(@object).and_return(false)
- NPlusOneQuery.stub(:association?).with(@object, :associations).and_return(false)
- NPlusOneQuery.send(:conditions_met?, @object, :associations).should be_true
+ NPlusOneQuery.stub(:possible?).with(@post.ar_key).and_return(true)
+ NPlusOneQuery.stub(:impossible?).with(@post.ar_key).and_return(false)
+ NPlusOneQuery.stub(:association?).with(@post.ar_key, :associations).and_return(false)
+ NPlusOneQuery.send(:conditions_met?, @post.ar_key, :associations).should be_true
end
it "should be false if object is not possible, not impossible and object, associations pair is not already existed" do
- NPlusOneQuery.stub(:possible?).with(@object).and_return(false)
- NPlusOneQuery.stub(:impossible?).with(@object).and_return(false)
- NPlusOneQuery.stub(:association?).with(@object, :associations).and_return(false)
- NPlusOneQuery.send(:conditions_met?, @object, :associations).should be_false
+ NPlusOneQuery.stub(:possible?).with(@post.ar_key).and_return(false)
+ NPlusOneQuery.stub(:impossible?).with(@post.ar_key).and_return(false)
+ NPlusOneQuery.stub(:association?).with(@post.ar_key, :associations).and_return(false)
+ NPlusOneQuery.send(:conditions_met?, @post.ar_key, :associations).should be_false
end
it "should be false if object is possible, but impossible and object, associations pair is not already existed" do
- NPlusOneQuery.stub(:possible?).with(@object).and_return(true)
- NPlusOneQuery.stub(:impossible?).with(@object).and_return(true)
- NPlusOneQuery.stub(:association?).with(@object, :associations).and_return(false)
- NPlusOneQuery.send(:conditions_met?, @object, :associations).should be_false
+ NPlusOneQuery.stub(:possible?).with(@post.ar_key).and_return(true)
+ NPlusOneQuery.stub(:impossible?).with(@post.ar_key).and_return(true)
+ NPlusOneQuery.stub(:association?).with(@post.ar_key, :associations).and_return(false)
+ NPlusOneQuery.send(:conditions_met?, @post.ar_key, :associations).should be_false
end
it "should be false if object is possible, not impossible and object, associations pair is already existed" do
- NPlusOneQuery.stub(:possible?).with(@object).and_return(true)
- NPlusOneQuery.stub(:impossible?).with(@object).and_return(false)
- NPlusOneQuery.stub(:association?).with(@object, :associations).and_return(true)
- NPlusOneQuery.send(:conditions_met?, @object, :associations).should be_false
+ NPlusOneQuery.stub(:possible?).with(@post.ar_key).and_return(true)
+ NPlusOneQuery.stub(:impossible?).with(@post.ar_key).and_return(false)
+ NPlusOneQuery.stub(:association?).with(@post.ar_key, :associations).and_return(true)
+ NPlusOneQuery.send(:conditions_met?, @post.ar_key, :associations).should be_false
end
end
context ".call_association" do
it "should create notification if conditions met" do
- NPlusOneQuery.should_receive(:conditions_met?).with(@object, :association).and_return(true)
+ NPlusOneQuery.should_receive(:conditions_met?).with(@post.ar_key, :association).and_return(true)
NPlusOneQuery.should_receive(:caller_in_project).and_return(["caller"])
- NPlusOneQuery.should_receive(:create_notification).with(["caller"], Object, :association)
- NPlusOneQuery.call_association(@object, :association)
+ NPlusOneQuery.should_receive(:create_notification).with(["caller"], "Post", :association)
+ NPlusOneQuery.call_association(@post, :association)
end
it "should not create notification if conditions not met" do
- NPlusOneQuery.should_receive(:conditions_met?).with(@object, :association).and_return(false)
+ NPlusOneQuery.should_receive(:conditions_met?).with(@post.ar_key, :association).and_return(false)
NPlusOneQuery.should_not_receive(:caller_in_project!)
- NPlusOneQuery.should_not_receive(:create_notification).with(Object, :association)
- NPlusOneQuery.call_association(@object, :association)
+ NPlusOneQuery.should_not_receive(:create_notification).with("Post", :association)
+ NPlusOneQuery.call_association(@post, :association)
end
end
end
View
38 spec/bullet/detector/unused_eager_association_spec.rb
@@ -3,35 +3,35 @@
module Bullet
module Detector
describe UnusedEagerAssociation do
- before(:each) { @object = Object.new }
- after(:each) { UnusedEagerAssociation.clear }
+ before(:all) { @post = Post.first }
+ before(:each) { UnusedEagerAssociation.clear }
context ".call_associations" do
it "should get empty array if eager_loadgins" do
- UnusedEagerAssociation.send(:call_associations, @object, Set.new([:association])).should be_empty
+ UnusedEagerAssociation.send(:call_associations, @post.ar_key, Set.new([:association])).should be_empty
end
it "should get call associations if object and association are both in eager_loadings and call_object_associations" do
- UnusedEagerAssociation.add_eager_loadings(@object, :association)
- UnusedEagerAssociation.add_call_object_associations(@object, :association)
- UnusedEagerAssociation.send(:call_associations, @object, Set.new([:association])).should == [:association]
+ UnusedEagerAssociation.add_eager_loadings(@post, :association)
+ UnusedEagerAssociation.add_call_object_associations(@post, :association)
+ UnusedEagerAssociation.send(:call_associations, @post.ar_key, Set.new([:association])).should == [:association]
end
it "should not get call associations if not exist in call_object_associations" do
- UnusedEagerAssociation.add_eager_loadings(@object, :association)
- UnusedEagerAssociation.send(:call_associations, @object, Set.new([:association])).should be_empty
+ UnusedEagerAssociation.add_eager_loadings(@post, :association)
+ UnusedEagerAssociation.send(:call_associations, @post.ar_key, Set.new([:association])).should be_empty
end
end
context ".diff_object_association" do
it "should return associations not exist in call_association" do
- UnusedEagerAssociation.send(:diff_object_association, @object, Set.new([:association])).should == [:association]
+ UnusedEagerAssociation.send(:diff_object_association, @post.ar_key, Set.new([:association])).should == [:association]
end
it "should return empty if associations exist in call_association" do
- UnusedEagerAssociation.add_eager_loadings(@object, :association)
- UnusedEagerAssociation.add_call_object_associations(@object, :association)
- UnusedEagerAssociation.send(:diff_object_association, @object, Set.new([:association])).should be_empty
+ UnusedEagerAssociation.add_eager_loadings(@post, :association)
+ UnusedEagerAssociation.add_call_object_associations(@post, :association)
+ UnusedEagerAssociation.send(:diff_object_association, @post.ar_key, Set.new([:association])).should be_empty
end
end
@@ -42,18 +42,18 @@ module Detector
end
it "should create notification if object_association_diff is not empty" do
- UnusedEagerAssociation.add_object_associations(@object, :association)
- UnusedEagerAssociation.should_receive(:create_notification).with(Object, [:association])
+ UnusedEagerAssociation.add_object_associations(@post, :association)
+ UnusedEagerAssociation.should_receive(:create_notification).with("Post", [:association])
UnusedEagerAssociation.check_unused_preload_associations
end
it "should not create notification if object_association_diff is empty" do
UnusedEagerAssociation.clear
- UnusedEagerAssociation.add_object_associations(@object, :association)
- UnusedEagerAssociation.add_eager_loadings(@object, :association)
- UnusedEagerAssociation.add_call_object_associations(@object, :association)
- UnusedEagerAssociation.send(:diff_object_association, @object, Set.new([:association])).should be_empty
- UnusedEagerAssociation.should_not_receive(:create_notification).with(Object, [:association])
+ UnusedEagerAssociation.add_object_associations(@post, :association)
+ UnusedEagerAssociation.add_eager_loadings(@post, :association)
+ UnusedEagerAssociation.add_call_object_associations(@post, :association)
+ UnusedEagerAssociation.send(:diff_object_association, @post.ar_key, Set.new([:association])).should be_empty
+ UnusedEagerAssociation.should_not_receive(:create_notification).with("Post", [:association])
UnusedEagerAssociation.check_unused_preload_associations
end
end
View
22 spec/bullet/registry/object_spec.rb
@@ -3,31 +3,27 @@
module Bullet
module Registry
- class Post; end
-
describe Object do
- let(:post) { Post.new }
- subject { Object.new.tap { |object| object.add(post) } }
+ let(:post) { Post.first }
+ let(:another_post) { Post.last }
+ subject { Object.new.tap { |object| object.add(post.ar_key) } }
context "#include?" do
it "should include the object" do
- subject.should be_include(post)
+ subject.should be_include(post.ar_key)
end
end
context "#add" do
it "should add an object" do
- post1 = Post.new
- subject.add(post1)
- subject.should be_include(post1)
+ subject.add(another_post.ar_key)
+ subject.should be_include(another_post.ar_key)
end
it "should add an array of objects" do
- post1 = Post.new
- post2 = Post.new
- subject.add([post1, post2])
- subject.should be_include(post1)
- subject.should be_include(post2)
+ subject.add([post.ar_key, another_post.ar_key])
+ subject.should be_include(post.ar_key)
+ subject.should be_include(another_post.ar_key)
end
end
end
View
2  spec/integration/association_for_chris_spec.rb
@@ -3,6 +3,7 @@
# This test is just used for http://github.com/flyerhzm/bullet/issues/#issue/14
describe Bullet::Detector::Association do
before(:each) do
+ Bullet.clear
Bullet.start_request
end
@@ -29,6 +30,7 @@
Deal.includes({:hotel => :location}).each do |deal|
deal.hotel.location.name
end
+ Bullet::Detector::UnusedEagerAssociation.check_unused_preload_associations
Bullet::Detector::Association.should_not be_has_unused_preload_associations
end
end
View
1  spec/integration/association_for_peschkaj_spec.rb
@@ -3,6 +3,7 @@
# This test is just used for http://github.com/flyerhzm/bullet/issues#issue/20
describe Bullet::Detector::Association do
before(:each) do
+ Bullet.clear
Bullet.start_request
end
View
60 spec/spec_helper.rb
@@ -42,63 +42,3 @@ def root
config.filter_run :focus => true
config.run_all_when_everything_filtered = true
end
-
-module Bullet
- def self.collected_notifications_of_class( notification_class )
- Bullet.notification_collector.collection.select do |notification|
- notification.is_a? notification_class
- end
- end
-
- def self.collected_counter_cache_notifications
- collected_notifications_of_class Bullet::Notification::CounterCache
- end
-
- def self.collected_n_plus_one_query_notifications
- collected_notifications_of_class Bullet::Notification::NPlusOneQuery
- end
-
- def self.collected_unused_eager_association_notifications
- collected_notifications_of_class Bullet::Notification::UnusedEagerLoading
- end
-end
-
-module Bullet
- module Detector
- class Association
- class <<self
- # returns true if all associations are preloaded
- def completely_preloading_associations?
- Bullet.collected_n_plus_one_query_notifications.empty?
- end
-
- def has_unused_preload_associations?
- Bullet.collected_unused_eager_association_notifications.present?
- end
-
- # returns true if a given object has a specific association
- def creating_object_association_for?(object, association)
- object_associations[object].present? && object_associations[object].include?(association)
- end
-
- # returns true if a given class includes the specific unpreloaded association
- def detecting_unpreloaded_association_for?(klass, association)
- for_class_and_assoc = Bullet.collected_n_plus_one_query_notifications.select do |notification|
- notification.base_class == klass and
- notification.associations.include?( association )
- end
- for_class_and_assoc.present?
- end
-
- # returns true if the given class includes the specific unused preloaded association
- def unused_preload_associations_for?(klass, association)
- for_class_and_assoc = Bullet.collected_unused_eager_association_notifications.select do |notification|
- notification.base_class == klass and
- notification.associations.include?( association )
- end
- for_class_and_assoc.present?
- end
- end
- end
- end
-end
View
55 spec/support/bullet_ext.rb
@@ -0,0 +1,55 @@
+module Bullet
+ def self.collected_notifications_of_class(notification_class)
+ Bullet.notification_collector.collection.select do |notification|
+ notification.is_a? notification_class
+ end
+ end
+
+ def self.collected_counter_cache_notifications
+ collected_notifications_of_class Bullet::Notification::CounterCache
+ end
+
+ def self.collected_n_plus_one_query_notifications
+ collected_notifications_of_class Bullet::Notification::NPlusOneQuery
+ end
+
+ def self.collected_unused_eager_association_notifications
+ collected_notifications_of_class Bullet::Notification::UnusedEagerLoading
+ end
+end
+
+module Bullet
+ module Detector
+ class Association
+ class <<self
+ # returns true if all associations are preloaded
+ def completely_preloading_associations?
+ Bullet.collected_n_plus_one_query_notifications.empty?
+ end
+
+ def has_unused_preload_associations?
+ Bullet.collected_unused_eager_association_notifications.present?
+ end
+
+ # returns true if a given object has a specific association
+ def creating_object_association_for?(object, association)
+ object_associations[object.ar_key].present? && object_associations[object.ar_key].include?(association)
+ end
+
+ # returns true if a given class includes the specific unpreloaded association
+ def detecting_unpreloaded_association_for?(klass, association)
+ Bullet.collected_n_plus_one_query_notifications.select { |notification|
+ notification.base_class == klass.to_s && notification.associations.include?(association)
+ }.present?
+ end
+
+ # returns true if the given class includes the specific unused preloaded association
+ def unused_preload_associations_for?(klass, association)
+ Bullet.collected_unused_eager_association_notifications.select { |notification|
+ notification.base_class == klass.to_s && notification.associations.include?(association)
+ }.present?
+ end
+ end
+ end
+ end
+end
Please sign in to comment.
Something went wrong with that request. Please try again.