bullet 7.0.7 → 7.1.0

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.
Files changed (108) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +9 -1
  3. data/README.md +3 -0
  4. data/lib/bullet/active_record4.rb +9 -0
  5. data/lib/bullet/active_record41.rb +9 -0
  6. data/lib/bullet/active_record42.rb +9 -0
  7. data/lib/bullet/active_record5.rb +11 -0
  8. data/lib/bullet/active_record52.rb +11 -0
  9. data/lib/bullet/active_record60.rb +11 -0
  10. data/lib/bullet/active_record61.rb +11 -0
  11. data/lib/bullet/active_record70.rb +19 -6
  12. data/lib/bullet/active_record71.rb +297 -0
  13. data/lib/bullet/dependency.rb +12 -0
  14. data/lib/bullet/detector/unused_eager_loading.rb +1 -1
  15. data/lib/bullet/mongoid8x.rb +59 -0
  16. data/lib/bullet/notification/counter_cache.rb +1 -1
  17. data/lib/bullet/rack.rb +1 -1
  18. data/lib/bullet/version.rb +1 -1
  19. data/lib/bullet.rb +5 -1
  20. metadata +7 -155
  21. data/.github/workflows/main.yml +0 -82
  22. data/.gitignore +0 -15
  23. data/.rspec +0 -2
  24. data/Gemfile +0 -24
  25. data/Gemfile.mongoid +0 -12
  26. data/Gemfile.mongoid-4.0 +0 -15
  27. data/Gemfile.mongoid-5.0 +0 -15
  28. data/Gemfile.mongoid-6.0 +0 -15
  29. data/Gemfile.mongoid-7.0 +0 -15
  30. data/Gemfile.rails-4.0 +0 -16
  31. data/Gemfile.rails-4.1 +0 -16
  32. data/Gemfile.rails-4.2 +0 -16
  33. data/Gemfile.rails-5.0 +0 -15
  34. data/Gemfile.rails-5.1 +0 -15
  35. data/Gemfile.rails-5.2 +0 -15
  36. data/Gemfile.rails-6.0 +0 -15
  37. data/Gemfile.rails-6.1 +0 -15
  38. data/Gemfile.rails-7.0 +0 -10
  39. data/Guardfile +0 -8
  40. data/Hacking.md +0 -75
  41. data/Rakefile +0 -51
  42. data/bullet.gemspec +0 -33
  43. data/perf/benchmark.rb +0 -118
  44. data/rails/init.rb +0 -3
  45. data/spec/bullet/detector/association_spec.rb +0 -28
  46. data/spec/bullet/detector/base_spec.rb +0 -10
  47. data/spec/bullet/detector/counter_cache_spec.rb +0 -58
  48. data/spec/bullet/detector/n_plus_one_query_spec.rb +0 -150
  49. data/spec/bullet/detector/unused_eager_loading_spec.rb +0 -126
  50. data/spec/bullet/ext/object_spec.rb +0 -44
  51. data/spec/bullet/ext/string_spec.rb +0 -15
  52. data/spec/bullet/notification/base_spec.rb +0 -94
  53. data/spec/bullet/notification/counter_cache_spec.rb +0 -14
  54. data/spec/bullet/notification/n_plus_one_query_spec.rb +0 -29
  55. data/spec/bullet/notification/unused_eager_loading_spec.rb +0 -18
  56. data/spec/bullet/notification_collector_spec.rb +0 -34
  57. data/spec/bullet/rack_spec.rb +0 -296
  58. data/spec/bullet/registry/association_spec.rb +0 -28
  59. data/spec/bullet/registry/base_spec.rb +0 -46
  60. data/spec/bullet/registry/object_spec.rb +0 -26
  61. data/spec/bullet/stack_trace_filter_spec.rb +0 -26
  62. data/spec/bullet_spec.rb +0 -136
  63. data/spec/integration/active_record/association_spec.rb +0 -822
  64. data/spec/integration/counter_cache_spec.rb +0 -68
  65. data/spec/integration/mongoid/association_spec.rb +0 -246
  66. data/spec/models/address.rb +0 -5
  67. data/spec/models/attachment.rb +0 -5
  68. data/spec/models/author.rb +0 -5
  69. data/spec/models/base_user.rb +0 -7
  70. data/spec/models/category.rb +0 -12
  71. data/spec/models/city.rb +0 -5
  72. data/spec/models/client.rb +0 -8
  73. data/spec/models/comment.rb +0 -8
  74. data/spec/models/company.rb +0 -5
  75. data/spec/models/country.rb +0 -5
  76. data/spec/models/deal.rb +0 -5
  77. data/spec/models/document.rb +0 -7
  78. data/spec/models/entry.rb +0 -5
  79. data/spec/models/firm.rb +0 -7
  80. data/spec/models/folder.rb +0 -4
  81. data/spec/models/group.rb +0 -4
  82. data/spec/models/mongoid/address.rb +0 -9
  83. data/spec/models/mongoid/category.rb +0 -10
  84. data/spec/models/mongoid/comment.rb +0 -9
  85. data/spec/models/mongoid/company.rb +0 -9
  86. data/spec/models/mongoid/entry.rb +0 -9
  87. data/spec/models/mongoid/post.rb +0 -14
  88. data/spec/models/mongoid/user.rb +0 -7
  89. data/spec/models/newspaper.rb +0 -5
  90. data/spec/models/page.rb +0 -4
  91. data/spec/models/person.rb +0 -5
  92. data/spec/models/pet.rb +0 -5
  93. data/spec/models/post.rb +0 -34
  94. data/spec/models/relationship.rb +0 -6
  95. data/spec/models/reply.rb +0 -5
  96. data/spec/models/role.rb +0 -7
  97. data/spec/models/student.rb +0 -5
  98. data/spec/models/submission.rb +0 -7
  99. data/spec/models/teacher.rb +0 -5
  100. data/spec/models/user.rb +0 -8
  101. data/spec/models/writer.rb +0 -4
  102. data/spec/spec_helper.rb +0 -97
  103. data/spec/support/bullet_ext.rb +0 -56
  104. data/spec/support/mongo_seed.rb +0 -59
  105. data/spec/support/rack_double.rb +0 -49
  106. data/spec/support/sqlite_seed.rb +0 -284
  107. data/test.sh +0 -15
  108. data/update.sh +0 -10
data/Rakefile DELETED
@@ -1,51 +0,0 @@
1
- $LOAD_PATH.unshift File.expand_path('lib', __dir__)
2
- require 'bundler'
3
- Bundler.setup
4
-
5
- require 'rake'
6
- require 'rspec'
7
- require 'rspec/core/rake_task'
8
-
9
- require 'bullet/version'
10
-
11
- task :build do
12
- system 'gem build bullet.gemspec'
13
- end
14
-
15
- task install: :build do
16
- system "sudo gem install bullet-#{Bullet::VERSION}.gem"
17
- end
18
-
19
- task release: :build do
20
- puts "Tagging #{Bullet::VERSION}..."
21
- system "git tag -a #{Bullet::VERSION} -m 'Tagging #{Bullet::VERSION}'"
22
- puts 'Pushing to Github...'
23
- system 'git push --tags'
24
- puts 'Pushing to rubygems.org...'
25
- system "gem push bullet-#{Bullet::VERSION}.gem"
26
- end
27
-
28
- RSpec::Core::RakeTask.new(:spec) do |spec|
29
- spec.pattern = 'spec/**/*_spec.rb'
30
- end
31
-
32
- RSpec::Core::RakeTask.new('spec:progress') do |spec|
33
- spec.rspec_opts = %w[--format progress]
34
- spec.pattern = 'spec/**/*_spec.rb'
35
- end
36
-
37
- begin
38
- require 'rdoc/task'
39
-
40
- desc 'Generate documentation for the plugin.'
41
- Rake::RDocTask.new do |rdoc|
42
- rdoc.rdoc_dir = 'rdoc'
43
- rdoc.title = "bullet #{Bullet::VERSION}"
44
- rdoc.rdoc_files.include('README*')
45
- rdoc.rdoc_files.include('lib/**/*.rb')
46
- end
47
- rescue LoadError
48
- puts 'RDocTask is not supported for this platform'
49
- end
50
-
51
- task default: :spec
data/bullet.gemspec DELETED
@@ -1,33 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- lib = File.expand_path('lib', __dir__)
4
- $LOAD_PATH.unshift lib unless $LOAD_PATH.include?(lib)
5
-
6
- require 'bullet/version'
7
-
8
- Gem::Specification.new do |s|
9
- s.name = 'bullet'
10
- s.version = Bullet::VERSION
11
- s.platform = Gem::Platform::RUBY
12
- s.authors = ['Richard Huang']
13
- s.email = ['flyerhzm@gmail.com']
14
- s.homepage = 'https://github.com/flyerhzm/bullet'
15
- s.summary = 'help to kill N+1 queries and unused eager loading.'
16
- s.description = 'help to kill N+1 queries and unused eager loading.'
17
- s.metadata = {
18
- 'changelog_uri' => 'https://github.com/flyerhzm/bullet/blob/master/CHANGELOG.md',
19
- 'source_code_uri' => 'https://github.com/flyerhzm/bullet'
20
- }
21
-
22
- s.license = 'MIT'
23
-
24
- s.required_ruby_version = '>= 2.3'
25
- s.required_rubygems_version = '>= 1.3.6'
26
-
27
- s.add_runtime_dependency 'activesupport', '>= 3.0.0'
28
- s.add_runtime_dependency 'uniform_notifier', '~> 1.11'
29
-
30
- s.files = `git ls-files`.split("\n")
31
- s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
32
- s.require_paths = ['lib']
33
- end
data/perf/benchmark.rb DELETED
@@ -1,118 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- $LOAD_PATH << 'lib'
4
- require 'benchmark'
5
- require 'rails'
6
- require 'active_record'
7
- require 'activerecord-import'
8
- require 'bullet'
9
-
10
- begin
11
- require 'perftools'
12
- rescue LoadError
13
- puts "Could not load perftools.rb, profiling won't be possible"
14
- end
15
-
16
- class Post < ActiveRecord::Base
17
- belongs_to :user
18
- has_many :comments
19
- end
20
-
21
- class Comment < ActiveRecord::Base
22
- belongs_to :user
23
- belongs_to :post
24
- end
25
-
26
- class User < ActiveRecord::Base
27
- has_many :posts
28
- has_many :comments
29
- end
30
-
31
- # create database bullet_benchmark;
32
- ActiveRecord::Base.establish_connection(
33
- adapter: 'mysql2',
34
- database: 'bullet_benchmark',
35
- server: '/tmp/mysql.socket',
36
- username: 'root'
37
- )
38
-
39
- ActiveRecord::Base.connection.tables.each { |table| ActiveRecord::Base.connection.drop_table(table) }
40
-
41
- ActiveRecord::Schema.define(version: 1) do
42
- create_table :posts do |t|
43
- t.column :title, :string
44
- t.column :body, :string
45
- t.column :user_id, :integer
46
- end
47
-
48
- create_table :comments do |t|
49
- t.column :body, :string
50
- t.column :post_id, :integer
51
- t.column :user_id, :integer
52
- end
53
-
54
- create_table :users do |t|
55
- t.column :name, :string
56
- end
57
- end
58
-
59
- users_size = 100
60
- posts_size = 1_000
61
- comments_size = 10_000
62
- users = []
63
- users_size.times { |i| users << User.new(name: "user#{i}") }
64
- User.import users
65
- users = User.all
66
-
67
- posts = []
68
- posts_size.times { |i| posts << Post.new(title: "Title #{i}", body: "Body #{i}", user: users[i % 100]) }
69
- Post.import posts
70
- posts = Post.all
71
-
72
- comments = []
73
- comments_size.times { |i| comments << Comment.new(body: "Comment #{i}", post: posts[i % 1_000], user: users[i % 100]) }
74
- Comment.import comments
75
-
76
- puts 'Start benchmarking...'
77
-
78
- Bullet.enable = true
79
-
80
- Benchmark.bm(70) do |bm|
81
- bm.report("Querying & Iterating #{posts_size} Posts with #{comments_size} Comments and #{users_size} Users") do
82
- 10.times do
83
- Bullet.start_request
84
- Post.select('SQL_NO_CACHE *').includes(:user, comments: :user).each do |p|
85
- p.title
86
- p.user.name
87
- p.comments.each do |c|
88
- c.body
89
- c.user.name
90
- end
91
- end
92
- Bullet.end_request
93
- end
94
- end
95
- end
96
-
97
- puts 'End benchmarking...'
98
-
99
- # Run benchmark with bundler
100
- #
101
- # bundle exec ruby perf/benchmark.rb
102
- #
103
- # bullet 2.3.0 with rails 3.2.2
104
- # user system total real
105
- # Querying & Iterating 1000 Posts with 10000 Comments and 100 Users 16.460000 0.190000 16.650000 ( 16.968246)
106
- #
107
- # bullet 2.3.0 with rails 3.1.4
108
- # user system total real
109
- # Querying & Iterating 1000 Posts with 10000 Comments and 100 Users 14.600000 0.130000 14.730000 ( 14.937590)
110
- #
111
- # bullet 2.3.0 with rails 3.0.12
112
- # user system total real
113
- # Querying & Iterating 1000 Posts with 10000 Comments and 100 Users 26.120000 0.430000 26.550000 ( 27.179304)
114
- #
115
- #
116
- # bullet 2.2.1 with rails 3.0.12
117
- # user system total real
118
- # Querying & Iterating 1000 Posts with 10000 Comments and 100 Users 29.970000 0.270000 30.240000 ( 30.452083)
data/rails/init.rb DELETED
@@ -1,3 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'bullet'
@@ -1,28 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'spec_helper'
4
-
5
- module Bullet
6
- module Detector
7
- describe Association do
8
- before :all do
9
- @post1 = Post.first
10
- @post2 = Post.last
11
- end
12
-
13
- context '.add_object_association' do
14
- it 'should add object, associations pair' do
15
- Association.add_object_associations(@post1, :associations)
16
- expect(Association.send(:object_associations)).to be_include(@post1.bullet_key, :associations)
17
- end
18
- end
19
-
20
- context '.add_call_object_associations' do
21
- it 'should add call object, associations pair' do
22
- Association.add_call_object_associations(@post1, :associations)
23
- expect(Association.send(:call_object_associations)).to be_include(@post1.bullet_key, :associations)
24
- end
25
- end
26
- end
27
- end
28
- end
@@ -1,10 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'spec_helper'
4
-
5
- module Bullet
6
- module Detector
7
- describe Base do
8
- end
9
- end
10
- end
@@ -1,58 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'spec_helper'
4
-
5
- module Bullet
6
- module Detector
7
- describe CounterCache do
8
- before :all do
9
- @post1 = Post.first
10
- @post2 = Post.last
11
- end
12
-
13
- context '.add_counter_cache' do
14
- it 'should create notification if conditions met' do
15
- expect(CounterCache).to receive(:conditions_met?).with(@post1, %i[comments]).and_return(true)
16
- expect(CounterCache).to receive(:create_notification).with('Post', %i[comments])
17
- CounterCache.add_counter_cache(@post1, %i[comments])
18
- end
19
-
20
- it 'should not create notification if conditions not met' do
21
- expect(CounterCache).to receive(:conditions_met?).with(@post1, %i[comments]).and_return(false)
22
- expect(CounterCache).to receive(:create_notification).never
23
- CounterCache.add_counter_cache(@post1, %i[comments])
24
- end
25
- end
26
-
27
- context '.add_possible_objects' do
28
- it 'should add possible objects' do
29
- CounterCache.add_possible_objects([@post1, @post2])
30
- expect(CounterCache.possible_objects).to be_include(@post1.bullet_key)
31
- expect(CounterCache.possible_objects).to be_include(@post2.bullet_key)
32
- end
33
-
34
- it 'should add impossible object' do
35
- CounterCache.add_impossible_object(@post1)
36
- expect(CounterCache.impossible_objects).to be_include(@post1.bullet_key)
37
- end
38
- end
39
-
40
- context '.conditions_met?' do
41
- it 'should be true when object is possible, not impossible' do
42
- CounterCache.add_possible_objects(@post1)
43
- expect(CounterCache.conditions_met?(@post1, :associations)).to eq true
44
- end
45
-
46
- it 'should be false when object is not possible' do
47
- expect(CounterCache.conditions_met?(@post1, :associations)).to eq false
48
- end
49
-
50
- it 'should be false when object is possible, and impossible' do
51
- CounterCache.add_possible_objects(@post1)
52
- CounterCache.add_impossible_object(@post1)
53
- expect(CounterCache.conditions_met?(@post1, :associations)).to eq false
54
- end
55
- end
56
- end
57
- end
58
- end
@@ -1,150 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'spec_helper'
4
-
5
- module Bullet
6
- module Detector
7
- describe NPlusOneQuery do
8
- before(:all) do
9
- @post = Post.first
10
- @post2 = Post.last
11
- end
12
-
13
- context '.call_association' do
14
- it 'should add call_object_associations' do
15
- expect(NPlusOneQuery).to receive(:add_call_object_associations).with(@post, :associations)
16
- NPlusOneQuery.call_association(@post, :associations)
17
- end
18
- end
19
-
20
- context '.possible?' do
21
- it 'should be true if possible_objects contain' do
22
- NPlusOneQuery.add_possible_objects(@post)
23
- expect(NPlusOneQuery.possible?(@post)).to eq true
24
- end
25
- end
26
-
27
- context '.impossible?' do
28
- it 'should be true if impossible_objects contain' do
29
- NPlusOneQuery.add_impossible_object(@post)
30
- expect(NPlusOneQuery.impossible?(@post)).to eq true
31
- end
32
- end
33
-
34
- context '.association?' do
35
- it 'should be true if object, associations pair is already existed' do
36
- NPlusOneQuery.add_object_associations(@post, :association)
37
- expect(NPlusOneQuery.association?(@post, :association)).to eq true
38
- end
39
-
40
- it 'should be false if object, association pair is not existed' do
41
- NPlusOneQuery.add_object_associations(@post, :association1)
42
- expect(NPlusOneQuery.association?(@post, :association2)).to eq false
43
- end
44
- end
45
-
46
- context '.conditions_met?' do
47
- it 'should be true if object is possible, not impossible and object, associations pair is not already existed' do
48
- allow(NPlusOneQuery).to receive(:possible?).with(@post).and_return(true)
49
- allow(NPlusOneQuery).to receive(:impossible?).with(@post).and_return(false)
50
- allow(NPlusOneQuery).to receive(:association?).with(@post, :associations).and_return(false)
51
- expect(NPlusOneQuery.conditions_met?(@post, :associations)).to eq true
52
- end
53
-
54
- it 'should be false if object is not possible, not impossible and object, associations pair is not already existed' do
55
- allow(NPlusOneQuery).to receive(:possible?).with(@post).and_return(false)
56
- allow(NPlusOneQuery).to receive(:impossible?).with(@post).and_return(false)
57
- allow(NPlusOneQuery).to receive(:association?).with(@post, :associations).and_return(false)
58
- expect(NPlusOneQuery.conditions_met?(@post, :associations)).to eq false
59
- end
60
-
61
- it 'should be false if object is possible, but impossible and object, associations pair is not already existed' do
62
- allow(NPlusOneQuery).to receive(:possible?).with(@post).and_return(true)
63
- allow(NPlusOneQuery).to receive(:impossible?).with(@post).and_return(true)
64
- allow(NPlusOneQuery).to receive(:association?).with(@post, :associations).and_return(false)
65
- expect(NPlusOneQuery.conditions_met?(@post, :associations)).to eq false
66
- end
67
-
68
- it 'should be false if object is possible, not impossible and object, associations pair is already existed' do
69
- allow(NPlusOneQuery).to receive(:possible?).with(@post).and_return(true)
70
- allow(NPlusOneQuery).to receive(:impossible?).with(@post).and_return(false)
71
- allow(NPlusOneQuery).to receive(:association?).with(@post, :associations).and_return(true)
72
- expect(NPlusOneQuery.conditions_met?(@post, :associations)).to eq false
73
- end
74
- end
75
-
76
- context '.call_association' do
77
- it 'should create notification if conditions met' do
78
- expect(NPlusOneQuery).to receive(:conditions_met?).with(@post, :association).and_return(true)
79
- expect(NPlusOneQuery).to receive(:caller_in_project).and_return(%w[caller])
80
- expect(NPlusOneQuery).to receive(:create_notification).with(%w[caller], 'Post', :association)
81
- NPlusOneQuery.call_association(@post, :association)
82
- end
83
-
84
- it 'should not create notification if conditions not met' do
85
- expect(NPlusOneQuery).to receive(:conditions_met?).with(@post, :association).and_return(false)
86
- expect(NPlusOneQuery).not_to receive(:caller_in_project!)
87
- expect(NPlusOneQuery).not_to receive(:create_notification).with('Post', :association)
88
- NPlusOneQuery.call_association(@post, :association)
89
- end
90
-
91
- context 'stacktrace_excludes' do
92
- before { Bullet.stacktrace_excludes = [/def/] }
93
- after { Bullet.stacktrace_excludes = nil }
94
-
95
- it 'should not create notification when stacktrace contains paths that are in the exclude list' do
96
- in_project = OpenStruct.new(absolute_path: File.join(Dir.pwd, 'abc', 'abc.rb'))
97
- included_path = OpenStruct.new(absolute_path: '/ghi/ghi.rb')
98
- excluded_path = OpenStruct.new(absolute_path: '/def/def.rb')
99
-
100
- expect(NPlusOneQuery).to receive(:caller_locations).and_return([in_project, included_path, excluded_path])
101
- expect(NPlusOneQuery).to_not receive(:create_notification)
102
- NPlusOneQuery.call_association(@post, :association)
103
- end
104
-
105
- # just a sanity spec to make sure the following spec works correctly
106
- it "should create notification when stacktrace contains methods that aren't in the exclude list" do
107
- method = NPlusOneQuery.method(:excluded_stacktrace_path?).source_location
108
- in_project = OpenStruct.new(absolute_path: File.join(Dir.pwd, 'abc', 'abc.rb'))
109
- excluded_path = OpenStruct.new(absolute_path: method.first, lineno: method.last)
110
-
111
- expect(NPlusOneQuery).to receive(:caller_locations).at_least(1).and_return([in_project, excluded_path])
112
- expect(NPlusOneQuery).to receive(:conditions_met?).and_return(true)
113
- expect(NPlusOneQuery).to receive(:create_notification)
114
- NPlusOneQuery.call_association(@post, :association)
115
- end
116
-
117
- it 'should not create notification when stacktrace contains methods that are in the exclude list' do
118
- method = NPlusOneQuery.method(:excluded_stacktrace_path?).source_location
119
- Bullet.stacktrace_excludes = [method]
120
- in_project = OpenStruct.new(absolute_path: File.join(Dir.pwd, 'abc', 'abc.rb'))
121
- excluded_path = OpenStruct.new(absolute_path: method.first, lineno: method.last)
122
-
123
- expect(NPlusOneQuery).to receive(:caller_locations).and_return([in_project, excluded_path])
124
- expect(NPlusOneQuery).to_not receive(:create_notification)
125
- NPlusOneQuery.call_association(@post, :association)
126
- end
127
- end
128
- end
129
-
130
- context '.add_possible_objects' do
131
- it 'should add possible objects' do
132
- NPlusOneQuery.add_possible_objects([@post, @post2])
133
- expect(NPlusOneQuery.possible_objects).to be_include(@post.bullet_key)
134
- expect(NPlusOneQuery.possible_objects).to be_include(@post2.bullet_key)
135
- end
136
-
137
- it 'should not raise error if object is nil' do
138
- expect { NPlusOneQuery.add_possible_objects(nil) }.not_to raise_error
139
- end
140
- end
141
-
142
- context '.add_impossible_object' do
143
- it 'should add impossible object' do
144
- NPlusOneQuery.add_impossible_object(@post)
145
- expect(NPlusOneQuery.impossible_objects).to be_include(@post.bullet_key)
146
- end
147
- end
148
- end
149
- end
150
- end
@@ -1,126 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'spec_helper'
4
-
5
- module Bullet
6
- module Detector
7
- describe UnusedEagerLoading do
8
- before(:all) do
9
- @post = Post.first
10
- @post2 = Post.all[1]
11
- @post3 = Post.last
12
- end
13
-
14
- context '.call_associations' do
15
- it 'should get empty array if eager_loadings' do
16
- expect(UnusedEagerLoading.send(:call_associations, @post.bullet_key, Set.new([:association]))).to be_empty
17
- end
18
-
19
- it 'should get call associations if object and association are both in eager_loadings and call_object_associations' do
20
- UnusedEagerLoading.add_eager_loadings([@post], :association)
21
- UnusedEagerLoading.add_call_object_associations(@post, :association)
22
- expect(UnusedEagerLoading.send(:call_associations, @post.bullet_key, Set.new([:association]))).to eq(
23
- [:association]
24
- )
25
- end
26
-
27
- it 'should not get call associations if not exist in call_object_associations' do
28
- UnusedEagerLoading.add_eager_loadings([@post], :association)
29
- expect(UnusedEagerLoading.send(:call_associations, @post.bullet_key, Set.new([:association]))).to be_empty
30
- end
31
- end
32
-
33
- context '.diff_object_associations' do
34
- it 'should return associations not exist in call_association' do
35
- expect(UnusedEagerLoading.send(:diff_object_associations, @post.bullet_key, Set.new([:association]))).to eq(
36
- [:association]
37
- )
38
- end
39
-
40
- it 'should return empty if associations exist in call_association' do
41
- UnusedEagerLoading.add_eager_loadings([@post], :association)
42
- UnusedEagerLoading.add_call_object_associations(@post, :association)
43
- expect(
44
- UnusedEagerLoading.send(:diff_object_associations, @post.bullet_key, Set.new([:association]))
45
- ).to be_empty
46
- end
47
- end
48
-
49
- context '.check_unused_preload_associations' do
50
- let(:paths) { %w[/dir1 /dir1/subdir] }
51
- it 'should create notification if object_association_diff is not empty' do
52
- UnusedEagerLoading.add_object_associations(@post, :association)
53
- allow(UnusedEagerLoading).to receive(:caller_in_project).and_return(paths)
54
- expect(UnusedEagerLoading).to receive(:create_notification).with(paths, 'Post', [:association])
55
- UnusedEagerLoading.check_unused_preload_associations
56
- end
57
-
58
- it 'should not create notification if object_association_diff is empty' do
59
- UnusedEagerLoading.add_object_associations(@post, :association)
60
- UnusedEagerLoading.add_eager_loadings([@post], :association)
61
- UnusedEagerLoading.add_call_object_associations(@post, :association)
62
- expect(
63
- UnusedEagerLoading.send(:diff_object_associations, @post.bullet_key, Set.new([:association]))
64
- ).to be_empty
65
- expect(UnusedEagerLoading).not_to receive(:create_notification).with('Post', [:association])
66
- UnusedEagerLoading.check_unused_preload_associations
67
- end
68
-
69
- it 'should create call stack for notification' do
70
- UnusedEagerLoading.add_object_associations(@post, :association)
71
- expect(UnusedEagerLoading.send(:call_stacks).registry).not_to be_empty
72
- end
73
- end
74
-
75
- context '.add_eager_loadings' do
76
- it 'should add objects, associations pair when eager_loadings are empty' do
77
- UnusedEagerLoading.add_eager_loadings([@post, @post2], :associations)
78
- expect(UnusedEagerLoading.send(:eager_loadings)).to be_include(
79
- [@post.bullet_key, @post2.bullet_key],
80
- :associations
81
- )
82
- end
83
-
84
- it 'should add objects, associations pair for existing eager_loadings' do
85
- UnusedEagerLoading.add_eager_loadings([@post, @post2], :association1)
86
- UnusedEagerLoading.add_eager_loadings([@post, @post2], :association2)
87
- expect(UnusedEagerLoading.send(:eager_loadings)).to be_include(
88
- [@post.bullet_key, @post2.bullet_key],
89
- :association1
90
- )
91
- expect(UnusedEagerLoading.send(:eager_loadings)).to be_include(
92
- [@post.bullet_key, @post2.bullet_key],
93
- :association2
94
- )
95
- end
96
-
97
- it 'should merge objects, associations pair for existing eager_loadings' do
98
- UnusedEagerLoading.add_eager_loadings([@post], :association1)
99
- UnusedEagerLoading.add_eager_loadings([@post, @post2], :association2)
100
- expect(UnusedEagerLoading.send(:eager_loadings)).to be_include([@post.bullet_key], :association1)
101
- expect(UnusedEagerLoading.send(:eager_loadings)).to be_include([@post.bullet_key], :association2)
102
- expect(UnusedEagerLoading.send(:eager_loadings)).to be_include([@post2.bullet_key], :association2)
103
- end
104
-
105
- it 'should vmerge objects recursively, associations pair for existing eager_loadings' do
106
- UnusedEagerLoading.add_eager_loadings([@post, @post2], :association1)
107
- UnusedEagerLoading.add_eager_loadings([@post, @post3], :association1)
108
- UnusedEagerLoading.add_eager_loadings([@post, @post3], :association2)
109
- expect(UnusedEagerLoading.send(:eager_loadings)).to be_include([@post.bullet_key], :association1)
110
- expect(UnusedEagerLoading.send(:eager_loadings)).to be_include([@post.bullet_key], :association2)
111
- expect(UnusedEagerLoading.send(:eager_loadings)).to be_include([@post2.bullet_key], :association1)
112
- expect(UnusedEagerLoading.send(:eager_loadings)).to be_include([@post3.bullet_key], :association1)
113
- expect(UnusedEagerLoading.send(:eager_loadings)).to be_include([@post3.bullet_key], :association2)
114
- end
115
-
116
- it 'should delete objects, associations pair for existing eager_loadings' do
117
- UnusedEagerLoading.add_eager_loadings([@post, @post2], :association1)
118
- UnusedEagerLoading.add_eager_loadings([@post], :association2)
119
- expect(UnusedEagerLoading.send(:eager_loadings)).to be_include([@post.bullet_key], :association1)
120
- expect(UnusedEagerLoading.send(:eager_loadings)).to be_include([@post.bullet_key], :association2)
121
- expect(UnusedEagerLoading.send(:eager_loadings)).to be_include([@post2.bullet_key], :association1)
122
- end
123
- end
124
- end
125
- end
126
- end
@@ -1,44 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'spec_helper'
4
-
5
- describe Object do
6
- context 'bullet_key' do
7
- it 'should return class and id composition' do
8
- post = Post.first
9
- expect(post.bullet_key).to eq("Post:#{post.id}")
10
- end
11
-
12
- if mongoid?
13
- it 'should return class with namespace and id composition' do
14
- post = Mongoid::Post.first
15
- expect(post.bullet_key).to eq("Mongoid::Post:#{post.id}")
16
- end
17
- end
18
- end
19
-
20
- context 'bullet_primary_key_value' do
21
- it 'should return id' do
22
- post = Post.first
23
- expect(post.bullet_primary_key_value).to eq(post.id)
24
- end
25
-
26
- it 'should return primary key value' do
27
- post = Post.first
28
- Post.primary_key = 'name'
29
- expect(post.bullet_primary_key_value).to eq(post.name)
30
- Post.primary_key = 'id'
31
- end
32
-
33
- it 'should return value for multiple primary keys' do
34
- post = Post.first
35
- allow(Post).to receive(:primary_keys).and_return(%i[category_id writer_id])
36
- expect(post.bullet_primary_key_value).to eq("#{post.category_id},#{post.writer_id}")
37
- end
38
-
39
- it 'it should return nil for unpersisted records' do
40
- post = Post.new(id: 123)
41
- expect(post.bullet_primary_key_value).to be_nil
42
- end
43
- end
44
- end
@@ -1,15 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'spec_helper'
4
-
5
- describe String do
6
- context 'bullet_class_name' do
7
- it 'should only return class name' do
8
- expect('Post:1'.bullet_class_name).to eq('Post')
9
- end
10
-
11
- it 'should return class name with namespace' do
12
- expect('Mongoid::Post:1234567890'.bullet_class_name).to eq('Mongoid::Post')
13
- end
14
- end
15
- end