bullet 5.7.0 → 5.7.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +5 -1
  3. data/Gemfile.rails-5.2 +1 -1
  4. data/Guardfile +1 -1
  5. data/README.md +3 -0
  6. data/Rakefile +4 -4
  7. data/bullet.gemspec +2 -3
  8. data/lib/bullet.rb +23 -23
  9. data/lib/bullet/active_record4.rb +3 -1
  10. data/lib/bullet/active_record41.rb +1 -1
  11. data/lib/bullet/active_record42.rb +8 -9
  12. data/lib/bullet/active_record5.rb +27 -28
  13. data/lib/bullet/active_record52.rb +27 -28
  14. data/lib/bullet/detector/association.rb +12 -12
  15. data/lib/bullet/detector/counter_cache.rb +7 -7
  16. data/lib/bullet/detector/n_plus_one_query.rb +6 -6
  17. data/lib/bullet/detector/unused_eager_loading.rb +23 -21
  18. data/lib/bullet/ext/object.rb +4 -4
  19. data/lib/bullet/ext/string.rb +1 -1
  20. data/lib/bullet/notification/base.rb +14 -14
  21. data/lib/bullet/notification/n_plus_one_query.rb +4 -4
  22. data/lib/bullet/notification/unused_eager_loading.rb +4 -4
  23. data/lib/bullet/notification_collector.rb +0 -1
  24. data/lib/bullet/version.rb +1 -2
  25. data/perf/benchmark.rb +7 -7
  26. data/spec/bullet/detector/n_plus_one_query_spec.rb +8 -8
  27. data/spec/bullet/ext/object_spec.rb +1 -1
  28. data/spec/bullet/notification/base_spec.rb +6 -6
  29. data/spec/bullet/notification/counter_cache_spec.rb +1 -1
  30. data/spec/bullet/notification/n_plus_one_query_spec.rb +1 -1
  31. data/spec/bullet/notification/unused_eager_loading_spec.rb +1 -1
  32. data/spec/bullet/rack_spec.rb +9 -10
  33. data/spec/bullet/registry/association_spec.rb +2 -2
  34. data/spec/bullet/registry/base_spec.rb +3 -3
  35. data/spec/bullet_spec.rb +7 -7
  36. data/spec/integration/active_record/association_spec.rb +16 -16
  37. data/spec/integration/counter_cache_spec.rb +2 -2
  38. data/spec/models/mongoid/address.rb +1 -1
  39. data/spec/models/mongoid/category.rb +2 -2
  40. data/spec/models/mongoid/comment.rb +1 -1
  41. data/spec/models/mongoid/company.rb +1 -1
  42. data/spec/models/mongoid/entry.rb +1 -1
  43. data/spec/models/mongoid/post.rb +4 -4
  44. data/spec/spec_helper.rb +1 -1
  45. data/spec/support/mongo_seed.rb +23 -23
  46. data/spec/support/rack_double.rb +7 -16
  47. data/spec/support/sqlite_seed.rb +73 -73
  48. metadata +5 -5
@@ -43,31 +43,31 @@ module Bullet
43
43
  # e.g. { "Post:1" => [:comments] }
44
44
  # the object_associations keep all associations that may be or may no be
45
45
  # unpreload associations or unused preload associations.
46
- def object_associations
47
- Thread.current[:bullet_object_associations]
48
- end
46
+ def object_associations
47
+ Thread.current[:bullet_object_associations]
48
+ end
49
49
 
50
50
  # call_object_associations keep the object relationships
51
51
  # that object.associations is called.
52
52
  # e.g. { "Post:1" => [:comments] }
53
53
  # they are used to detect unused preload associations.
54
- def call_object_associations
55
- Thread.current[:bullet_call_object_associations]
56
- end
54
+ def call_object_associations
55
+ Thread.current[:bullet_call_object_associations]
56
+ end
57
57
 
58
58
  # inversed_objects keeps object relationships
59
59
  # that association is inversed.
60
60
  # e.g. { "Comment:1" => ["post"] }
61
- def inversed_objects
62
- Thread.current[:bullet_inversed_objects]
63
- end
61
+ def inversed_objects
62
+ Thread.current[:bullet_inversed_objects]
63
+ end
64
64
 
65
65
  # eager_loadings keep the object relationships
66
66
  # that the associations are preloaded by find :include.
67
67
  # e.g. { ["Post:1", "Post:2"] => [:comments, :user] }
68
- def eager_loadings
69
- Thread.current[:bullet_eager_loadings]
70
- end
68
+ def eager_loadings
69
+ Thread.current[:bullet_eager_loadings]
70
+ end
71
71
  end
72
72
  end
73
73
  end
@@ -32,7 +32,7 @@ module Bullet
32
32
  impossible_objects.add object.bullet_key
33
33
  end
34
34
 
35
- def conditions_met?(object, associations)
35
+ def conditions_met?(object, _associations)
36
36
  possible_objects.include?(object.bullet_key) && !impossible_objects.include?(object.bullet_key)
37
37
  end
38
38
 
@@ -46,14 +46,14 @@ module Bullet
46
46
 
47
47
  private
48
48
 
49
- def create_notification(klazz, associations)
50
- notify_associations = Array(associations) - Bullet.get_whitelist_associations(:counter_cache, klazz)
49
+ def create_notification(klazz, associations)
50
+ notify_associations = Array(associations) - Bullet.get_whitelist_associations(:counter_cache, klazz)
51
51
 
52
- if notify_associations.present?
53
- notice = Bullet::Notification::CounterCache.new klazz, notify_associations
54
- Bullet.notification_collector.add notice
55
- end
52
+ if notify_associations.present?
53
+ notice = Bullet::Notification::CounterCache.new klazz, notify_associations
54
+ Bullet.notification_collector.add notice
56
55
  end
56
+ end
57
57
  end
58
58
  end
59
59
  end
@@ -82,14 +82,14 @@ module Bullet
82
82
 
83
83
  private
84
84
 
85
- def create_notification(callers, klazz, associations)
86
- notify_associations = Array(associations) - Bullet.get_whitelist_associations(:n_plus_one_query, klazz)
85
+ def create_notification(callers, klazz, associations)
86
+ notify_associations = Array(associations) - Bullet.get_whitelist_associations(:n_plus_one_query, klazz)
87
87
 
88
- if notify_associations.present?
89
- notice = Bullet::Notification::NPlusOneQuery.new(callers, klazz, notify_associations)
90
- Bullet.notification_collector.add(notice)
91
- end
88
+ if notify_associations.present?
89
+ notice = Bullet::Notification::NPlusOneQuery.new(callers, klazz, notify_associations)
90
+ Bullet.notification_collector.add(notice)
92
91
  end
92
+ end
93
93
  end
94
94
  end
95
95
  end
@@ -30,13 +30,15 @@ module Bullet
30
30
  Bullet.debug('Detector::UnusedEagerLoading#add_eager_loadings', "objects: #{objects.map(&:bullet_key).join(', ')}, associations: #{associations}")
31
31
  bullet_keys = objects.map(&:bullet_key)
32
32
 
33
- to_add, to_merge, to_delete = [], [], []
34
- eager_loadings.each do |k, v|
33
+ to_add = []
34
+ to_merge = []
35
+ to_delete = []
36
+ eager_loadings.each do |k, _v|
35
37
  key_objects_overlap = k & bullet_keys
36
38
 
37
39
  next if key_objects_overlap.empty?
38
40
 
39
- bullet_keys = bullet_keys - k
41
+ bullet_keys -= k
40
42
  if key_objects_overlap == k
41
43
  to_add << [k, associations]
42
44
  else
@@ -57,29 +59,29 @@ module Bullet
57
59
 
58
60
  private
59
61
 
60
- def create_notification(callers, klazz, associations)
61
- notify_associations = Array(associations) - Bullet.get_whitelist_associations(:unused_eager_loading, klazz)
62
+ def create_notification(callers, klazz, associations)
63
+ notify_associations = Array(associations) - Bullet.get_whitelist_associations(:unused_eager_loading, klazz)
62
64
 
63
- if notify_associations.present?
64
- notice = Bullet::Notification::UnusedEagerLoading.new(callers, klazz, notify_associations)
65
- Bullet.notification_collector.add(notice)
66
- end
65
+ if notify_associations.present?
66
+ notice = Bullet::Notification::UnusedEagerLoading.new(callers, klazz, notify_associations)
67
+ Bullet.notification_collector.add(notice)
67
68
  end
69
+ end
68
70
 
69
- def call_associations(bullet_key, associations)
70
- all = Set.new
71
- eager_loadings.similarly_associated(bullet_key, associations).each do |related_bullet_key|
72
- coa = call_object_associations[related_bullet_key]
73
- next if coa.nil?
74
- all.merge coa
75
- end
76
- all.to_a
71
+ def call_associations(bullet_key, associations)
72
+ all = Set.new
73
+ eager_loadings.similarly_associated(bullet_key, associations).each do |related_bullet_key|
74
+ coa = call_object_associations[related_bullet_key]
75
+ next if coa.nil?
76
+ all.merge coa
77
77
  end
78
+ all.to_a
79
+ end
78
80
 
79
- def diff_object_associations(bullet_key, associations)
80
- potential_associations = associations - call_associations(bullet_key, associations)
81
- potential_associations.reject { |a| a.is_a?(Hash) }
82
- end
81
+ def diff_object_associations(bullet_key, associations)
82
+ potential_associations = associations - call_associations(bullet_key, associations)
83
+ potential_associations.reject { |a| a.is_a?(Hash) }
84
+ end
83
85
  end
84
86
  end
85
87
  end
@@ -1,15 +1,15 @@
1
1
  class Object
2
2
  def bullet_key
3
- "#{self.class}:#{self.primary_key_value}"
3
+ "#{self.class}:#{primary_key_value}"
4
4
  end
5
5
 
6
6
  def primary_key_value
7
7
  if self.class.respond_to?(:primary_keys) && self.class.primary_keys
8
- self.class.primary_keys.map { |primary_key| self.send primary_key }.join(','.freeze)
8
+ self.class.primary_keys.map { |primary_key| send primary_key }.join(','.freeze)
9
9
  elsif self.class.respond_to?(:primary_key) && self.class.primary_key
10
- self.send self.class.primary_key
10
+ send self.class.primary_key
11
11
  else
12
- self.id
12
+ id
13
13
  end
14
14
  end
15
15
  end
@@ -1,5 +1,5 @@
1
1
  class String
2
2
  def bullet_class_name
3
- self.sub(/:[^:]*?$/, ''.freeze)
3
+ sub(/:[^:]*?$/, ''.freeze)
4
4
  end
5
5
  end
@@ -11,11 +11,11 @@ module Bullet
11
11
  end
12
12
 
13
13
  def title
14
- raise NoMethodError.new('no method title defined')
14
+ raise NoMethodError, 'no method title defined'
15
15
  end
16
16
 
17
17
  def body
18
- raise NoMethodError.new('no method body defined')
18
+ raise NoMethodError, 'no method body defined'
19
19
  end
20
20
 
21
21
  def call_stack_messages
@@ -36,11 +36,11 @@ module Bullet
36
36
  end
37
37
 
38
38
  def notify_inline
39
- self.notifier.inline_notify(notification_data)
39
+ notifier.inline_notify(notification_data)
40
40
  end
41
41
 
42
42
  def notify_out_of_channel
43
- self.notifier.out_of_channel_notify(notification_data)
43
+ notifier.out_of_channel_notify(notification_data)
44
44
  end
45
45
 
46
46
  def short_notice
@@ -49,10 +49,10 @@ module Bullet
49
49
 
50
50
  def notification_data
51
51
  {
52
- :user => whoami,
53
- :url => url,
54
- :title => title,
55
- :body => body_with_caller,
52
+ user: whoami,
53
+ url: url,
54
+ title: title,
55
+ body: body_with_caller
56
56
  }
57
57
  end
58
58
 
@@ -66,13 +66,13 @@ module Bullet
66
66
 
67
67
  protected
68
68
 
69
- def klazz_associations_str
70
- " #{@base_class} => [#{@associations.map(&:inspect).join(', '.freeze)}]"
71
- end
69
+ def klazz_associations_str
70
+ " #{@base_class} => [#{@associations.map(&:inspect).join(', '.freeze)}]"
71
+ end
72
72
 
73
- def associations_str
74
- ":includes => #{@associations.map { |a| a.to_s.to_sym unless a.is_a? Hash }.inspect}"
75
- end
73
+ def associations_str
74
+ ":includes => #{@associations.map { |a| a.to_s.to_sym unless a.is_a? Hash }.inspect}"
75
+ end
76
76
  end
77
77
  end
78
78
  end
@@ -17,15 +17,15 @@ module Bullet
17
17
 
18
18
  def notification_data
19
19
  super.merge(
20
- :backtrace => []
20
+ backtrace: []
21
21
  )
22
22
  end
23
23
 
24
24
  protected
25
25
 
26
- def call_stack_messages
27
- (['Call stack'] + @callers).join("\n ")
28
- end
26
+ def call_stack_messages
27
+ (['Call stack'] + @callers).join("\n ")
28
+ end
29
29
  end
30
30
  end
31
31
  end
@@ -17,15 +17,15 @@ module Bullet
17
17
 
18
18
  def notification_data
19
19
  super.merge(
20
- :backtrace => []
20
+ backtrace: []
21
21
  )
22
22
  end
23
23
 
24
24
  protected
25
25
 
26
- def call_stack_messages
27
- (['Call stack'] + @callers).join("\n ")
28
- end
26
+ def call_stack_messages
27
+ (['Call stack'] + @callers).join("\n ")
28
+ end
29
29
  end
30
30
  end
31
31
  end
@@ -21,4 +21,3 @@ module Bullet
21
21
  end
22
22
  end
23
23
  end
24
-
@@ -1,4 +1,3 @@
1
-
2
1
  module Bullet
3
- VERSION = '5.7.0'.freeze
2
+ VERSION = '5.7.1'.freeze
4
3
  end
@@ -1,4 +1,4 @@
1
- $: << 'lib'
1
+ $LOAD_PATH << 'lib'
2
2
  require 'benchmark'
3
3
  require 'rails'
4
4
  require 'active_record'
@@ -27,13 +27,13 @@ class User < ActiveRecord::Base
27
27
  end
28
28
 
29
29
  # create database bullet_benchmark;
30
- ActiveRecord::Base.establish_connection(:adapter => 'mysql2', :database => 'bullet_benchmark', :server => '/tmp/mysql.socket', :username => 'root')
30
+ ActiveRecord::Base.establish_connection(adapter: 'mysql2', database: 'bullet_benchmark', server: '/tmp/mysql.socket', username: 'root')
31
31
 
32
32
  ActiveRecord::Base.connection.tables.each do |table|
33
33
  ActiveRecord::Base.connection.drop_table(table)
34
34
  end
35
35
 
36
- ActiveRecord::Schema.define(:version => 1) do
36
+ ActiveRecord::Schema.define(version: 1) do
37
37
  create_table :posts do |t|
38
38
  t.column :title, :string
39
39
  t.column :body, :string
@@ -56,21 +56,21 @@ posts_size = 1000
56
56
  comments_size = 10_000
57
57
  users = []
58
58
  users_size.times do |i|
59
- users << User.new(:name => "user#{i}")
59
+ users << User.new(name: "user#{i}")
60
60
  end
61
61
  User.import users
62
62
  users = User.all
63
63
 
64
64
  posts = []
65
65
  posts_size.times do |i|
66
- posts << Post.new(:title => "Title #{i}", :body => "Body #{i}", :user => users[i % 100])
66
+ posts << Post.new(title: "Title #{i}", body: "Body #{i}", user: users[i % 100])
67
67
  end
68
68
  Post.import posts
69
69
  posts = Post.all
70
70
 
71
71
  comments = []
72
72
  comments_size.times do |i|
73
- comments << Comment.new(:body => "Comment #{i}", :post => posts[i % 1000], :user => users[i % 100])
73
+ comments << Comment.new(body: "Comment #{i}", post: posts[i % 1000], user: users[i % 100])
74
74
  end
75
75
  Comment.import comments
76
76
 
@@ -82,7 +82,7 @@ Benchmark.bm(70) do |bm|
82
82
  bm.report("Querying & Iterating #{posts_size} Posts with #{comments_size} Comments and #{users_size} Users") do
83
83
  10.times do
84
84
  Bullet.start_request
85
- Post.select('SQL_NO_CACHE *').includes(:user, :comments => :user).each do |p|
85
+ Post.select('SQL_NO_CACHE *').includes(:user, comments: :user).each do |p|
86
86
  p.title
87
87
  p.user.name
88
88
  p.comments.each do |c|
@@ -91,9 +91,9 @@ module Bullet
91
91
  after { Bullet.stacktrace_excludes = nil }
92
92
 
93
93
  it 'should not create notification when stacktrace contains paths that are in the exclude list' do
94
- in_project = OpenStruct.new(:absolute_path => File.join(Dir.pwd, 'abc', 'abc.rb'))
95
- included_path = OpenStruct.new(:absolute_path => '/ghi/ghi.rb')
96
- excluded_path = OpenStruct.new(:absolute_path => '/def/def.rb')
94
+ in_project = OpenStruct.new(absolute_path: File.join(Dir.pwd, 'abc', 'abc.rb'))
95
+ included_path = OpenStruct.new(absolute_path: '/ghi/ghi.rb')
96
+ excluded_path = OpenStruct.new(absolute_path: '/def/def.rb')
97
97
 
98
98
  expect(NPlusOneQuery).to receive(:caller_locations).and_return([in_project, included_path, excluded_path])
99
99
  expect(NPlusOneQuery).to_not receive(:create_notification)
@@ -104,8 +104,8 @@ module Bullet
104
104
 
105
105
  context '.caller_in_project' do
106
106
  it 'should include only paths that are in the project' do
107
- in_project = OpenStruct.new(:absolute_path => File.join(Dir.pwd, 'abc', 'abc.rb'))
108
- not_in_project = OpenStruct.new(:absolute_path => '/def/def.rb')
107
+ in_project = OpenStruct.new(absolute_path: File.join(Dir.pwd, 'abc', 'abc.rb'))
108
+ not_in_project = OpenStruct.new(absolute_path: '/def/def.rb')
109
109
 
110
110
  expect(NPlusOneQuery).to receive(:caller_locations).and_return([in_project, not_in_project])
111
111
  expect(NPlusOneQuery).to receive(:conditions_met?).with(@post, :association).and_return(true)
@@ -118,9 +118,9 @@ module Bullet
118
118
  after { Bullet.stacktrace_includes = nil }
119
119
 
120
120
  it 'should include paths that are in the stacktrace_include list' do
121
- in_project = OpenStruct.new(:absolute_path => File.join(Dir.pwd, 'abc', 'abc.rb'))
122
- included_gems = [OpenStruct.new(:absolute_path => '/def/def.rb'), OpenStruct.new(:absolute_path => 'xyz/xyz.rb')]
123
- excluded_gem = OpenStruct.new(:absolute_path => '/ghi/ghi.rb')
121
+ in_project = OpenStruct.new(absolute_path: File.join(Dir.pwd, 'abc', 'abc.rb'))
122
+ included_gems = [OpenStruct.new(absolute_path: '/def/def.rb'), OpenStruct.new(absolute_path: 'xyz/xyz.rb')]
123
+ excluded_gem = OpenStruct.new(absolute_path: '/ghi/ghi.rb')
124
124
 
125
125
  expect(NPlusOneQuery).to receive(:caller_locations).and_return([in_project, *included_gems, excluded_gem])
126
126
  expect(NPlusOneQuery).to receive(:conditions_met?).with(@post, :association).and_return(true)
@@ -30,7 +30,7 @@ describe Object do
30
30
 
31
31
  it 'should return value for multiple primary keys' do
32
32
  post = Post.first
33
- allow(Post).to receive(:primary_keys).and_return([:category_id, :writer_id])
33
+ allow(Post).to receive(:primary_keys).and_return(%i[category_id writer_id])
34
34
  expect(post.primary_key_value).to eq("#{post.category_id},#{post.writer_id}")
35
35
  end
36
36
  end
@@ -3,7 +3,7 @@ require 'spec_helper'
3
3
  module Bullet
4
4
  module Notification
5
5
  describe Base do
6
- subject { Base.new(Post, [:comments, :votes]) }
6
+ subject { Base.new(Post, %i[comments votes]) }
7
7
 
8
8
  context '#title' do
9
9
  it 'should raise NoMethodError' do
@@ -66,7 +66,7 @@ module Bullet
66
66
  allow(subject).to receive(:url).and_return('url')
67
67
  allow(subject).to receive(:title).and_return('title')
68
68
  allow(subject).to receive(:body_with_caller).and_return('body_with_caller')
69
- expect(subject.notification_data).to eq(:user => 'whoami', :url => 'url', :title => 'title', :body => 'body_with_caller')
69
+ expect(subject.notification_data).to eq(user: 'whoami', url: 'url', title: 'title', body: 'body_with_caller')
70
70
  end
71
71
  end
72
72
 
@@ -74,8 +74,8 @@ module Bullet
74
74
  it 'should send full_notice to notifier' do
75
75
  notifier = double
76
76
  allow(subject).to receive(:notifier).and_return(notifier)
77
- allow(subject).to receive(:notification_data).and_return(:foo => :bar)
78
- expect(notifier).to receive(:inline_notify).with(:foo => :bar)
77
+ allow(subject).to receive(:notification_data).and_return(foo: :bar)
78
+ expect(notifier).to receive(:inline_notify).with(foo: :bar)
79
79
  subject.notify_inline
80
80
  end
81
81
  end
@@ -84,8 +84,8 @@ module Bullet
84
84
  it 'should send full_out_of_channel to notifier' do
85
85
  notifier = double
86
86
  allow(subject).to receive(:notifier).and_return(notifier)
87
- allow(subject).to receive(:notification_data).and_return(:foo => :bar)
88
- expect(notifier).to receive(:out_of_channel_notify).with(:foo => :bar)
87
+ allow(subject).to receive(:notification_data).and_return(foo: :bar)
88
+ expect(notifier).to receive(:out_of_channel_notify).with(foo: :bar)
89
89
  subject.notify_out_of_channel
90
90
  end
91
91
  end