bullet 5.5.0 → 6.1.5

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 (123) hide show
  1. checksums.yaml +5 -5
  2. data/.github/workflows/main.yml +66 -0
  3. data/CHANGELOG.md +83 -1
  4. data/Gemfile +6 -1
  5. data/Gemfile.mongoid-7.0 +15 -0
  6. data/Gemfile.rails-4.0 +1 -1
  7. data/Gemfile.rails-4.1 +1 -1
  8. data/Gemfile.rails-4.2 +1 -1
  9. data/Gemfile.rails-5.0 +2 -2
  10. data/Gemfile.rails-5.1 +15 -0
  11. data/Gemfile.rails-5.2 +15 -0
  12. data/Gemfile.rails-6.0 +15 -0
  13. data/Gemfile.rails-6.1 +15 -0
  14. data/Guardfile +2 -2
  15. data/Hacking.md +1 -1
  16. data/README.md +58 -37
  17. data/Rakefile +20 -21
  18. data/bullet.gemspec +21 -15
  19. data/lib/bullet/active_job.rb +13 -0
  20. data/lib/bullet/active_record4.rb +15 -34
  21. data/lib/bullet/active_record41.rb +14 -31
  22. data/lib/bullet/active_record42.rb +23 -36
  23. data/lib/bullet/active_record5.rb +178 -158
  24. data/lib/bullet/active_record52.rb +251 -0
  25. data/lib/bullet/active_record60.rb +278 -0
  26. data/lib/bullet/active_record61.rb +278 -0
  27. data/lib/bullet/bullet_xhr.js +64 -0
  28. data/lib/bullet/dependency.rb +60 -32
  29. data/lib/bullet/detector/association.rb +41 -32
  30. data/lib/bullet/detector/base.rb +2 -0
  31. data/lib/bullet/detector/counter_cache.rb +25 -17
  32. data/lib/bullet/detector/n_plus_one_query.rb +38 -24
  33. data/lib/bullet/detector/unused_eager_loading.rb +35 -26
  34. data/lib/bullet/detector.rb +2 -0
  35. data/lib/bullet/ext/object.rb +9 -5
  36. data/lib/bullet/ext/string.rb +3 -1
  37. data/lib/bullet/mongoid4x.rb +9 -8
  38. data/lib/bullet/mongoid5x.rb +9 -8
  39. data/lib/bullet/mongoid6x.rb +13 -12
  40. data/lib/bullet/mongoid7x.rb +57 -0
  41. data/lib/bullet/notification/base.rb +28 -25
  42. data/lib/bullet/notification/counter_cache.rb +3 -1
  43. data/lib/bullet/notification/n_plus_one_query.rb +8 -7
  44. data/lib/bullet/notification/unused_eager_loading.rb +8 -7
  45. data/lib/bullet/notification.rb +4 -1
  46. data/lib/bullet/notification_collector.rb +2 -1
  47. data/lib/bullet/rack.rb +66 -35
  48. data/lib/bullet/registry/association.rb +2 -0
  49. data/lib/bullet/registry/base.rb +2 -0
  50. data/lib/bullet/registry/object.rb +2 -0
  51. data/lib/bullet/registry.rb +2 -0
  52. data/lib/bullet/stack_trace_filter.rb +50 -20
  53. data/lib/bullet/version.rb +3 -2
  54. data/lib/bullet.rb +136 -55
  55. data/lib/generators/bullet/install_generator.rb +48 -0
  56. data/perf/benchmark.rb +19 -22
  57. data/rails/init.rb +2 -0
  58. data/spec/bullet/detector/association_spec.rb +6 -4
  59. data/spec/bullet/detector/base_spec.rb +2 -0
  60. data/spec/bullet/detector/counter_cache_spec.rb +17 -15
  61. data/spec/bullet/detector/n_plus_one_query_spec.rb +75 -46
  62. data/spec/bullet/detector/unused_eager_loading_spec.rb +45 -26
  63. data/spec/bullet/ext/object_spec.rb +18 -11
  64. data/spec/bullet/ext/string_spec.rb +7 -5
  65. data/spec/bullet/notification/base_spec.rb +38 -39
  66. data/spec/bullet/notification/counter_cache_spec.rb +5 -3
  67. data/spec/bullet/notification/n_plus_one_query_spec.rb +20 -5
  68. data/spec/bullet/notification/unused_eager_loading_spec.rb +9 -3
  69. data/spec/bullet/notification_collector_spec.rb +12 -10
  70. data/spec/bullet/rack_spec.rb +200 -48
  71. data/spec/bullet/registry/association_spec.rb +12 -10
  72. data/spec/bullet/registry/base_spec.rb +22 -20
  73. data/spec/bullet/registry/object_spec.rb +6 -4
  74. data/spec/bullet_spec.rb +64 -33
  75. data/spec/integration/{active_record4 → active_record}/association_spec.rb +238 -223
  76. data/spec/integration/counter_cache_spec.rb +26 -44
  77. data/spec/integration/mongoid/association_spec.rb +53 -65
  78. data/spec/models/address.rb +2 -0
  79. data/spec/models/attachment.rb +5 -0
  80. data/spec/models/author.rb +2 -0
  81. data/spec/models/base_user.rb +2 -0
  82. data/spec/models/category.rb +2 -0
  83. data/spec/models/city.rb +2 -0
  84. data/spec/models/client.rb +4 -0
  85. data/spec/models/comment.rb +3 -1
  86. data/spec/models/company.rb +2 -0
  87. data/spec/models/country.rb +2 -0
  88. data/spec/models/deal.rb +5 -0
  89. data/spec/models/document.rb +4 -2
  90. data/spec/models/entry.rb +2 -0
  91. data/spec/models/firm.rb +3 -0
  92. data/spec/models/folder.rb +2 -0
  93. data/spec/models/group.rb +4 -0
  94. data/spec/models/mongoid/address.rb +3 -1
  95. data/spec/models/mongoid/category.rb +4 -2
  96. data/spec/models/mongoid/comment.rb +3 -1
  97. data/spec/models/mongoid/company.rb +3 -1
  98. data/spec/models/mongoid/entry.rb +3 -1
  99. data/spec/models/mongoid/post.rb +6 -4
  100. data/spec/models/mongoid/user.rb +2 -0
  101. data/spec/models/newspaper.rb +3 -1
  102. data/spec/models/page.rb +2 -0
  103. data/spec/models/person.rb +2 -0
  104. data/spec/models/pet.rb +2 -0
  105. data/spec/models/post.rb +19 -0
  106. data/spec/models/relationship.rb +2 -0
  107. data/spec/models/reply.rb +2 -0
  108. data/spec/models/student.rb +2 -0
  109. data/spec/models/submission.rb +3 -0
  110. data/spec/models/teacher.rb +2 -0
  111. data/spec/models/user.rb +3 -0
  112. data/spec/models/writer.rb +2 -0
  113. data/spec/spec_helper.rb +19 -23
  114. data/spec/support/bullet_ext.rb +10 -9
  115. data/spec/support/mongo_seed.rb +38 -57
  116. data/spec/support/rack_double.rb +13 -19
  117. data/spec/support/sqlite_seed.rb +104 -76
  118. data/tasks/bullet_tasks.rake +4 -2
  119. data/test.sh +5 -0
  120. data/update.sh +3 -0
  121. metadata +34 -17
  122. data/.travis.yml +0 -16
  123. data/spec/integration/active_record5/association_spec.rb +0 -768
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  module Bullet
@@ -8,62 +10,62 @@ module Bullet
8
10
  @post2 = Post.last
9
11
  end
10
12
 
11
- context ".call_association" do
12
- it "should add call_object_associations" do
13
+ context '.call_association' do
14
+ it 'should add call_object_associations' do
13
15
  expect(NPlusOneQuery).to receive(:add_call_object_associations).with(@post, :associations)
14
16
  NPlusOneQuery.call_association(@post, :associations)
15
17
  end
16
18
  end
17
19
 
18
- context ".possible?" do
19
- it "should be true if possible_objects contain" do
20
+ context '.possible?' do
21
+ it 'should be true if possible_objects contain' do
20
22
  NPlusOneQuery.add_possible_objects(@post)
21
23
  expect(NPlusOneQuery.possible?(@post)).to eq true
22
24
  end
23
25
  end
24
26
 
25
- context ".impossible?" do
26
- it "should be true if impossible_objects contain" do
27
+ context '.impossible?' do
28
+ it 'should be true if impossible_objects contain' do
27
29
  NPlusOneQuery.add_impossible_object(@post)
28
30
  expect(NPlusOneQuery.impossible?(@post)).to eq true
29
31
  end
30
32
  end
31
33
 
32
- context ".association?" do
33
- it "should be true if object, associations pair is already existed" do
34
+ context '.association?' do
35
+ it 'should be true if object, associations pair is already existed' do
34
36
  NPlusOneQuery.add_object_associations(@post, :association)
35
37
  expect(NPlusOneQuery.association?(@post, :association)).to eq true
36
38
  end
37
39
 
38
- it "should be false if object, association pair is not existed" do
40
+ it 'should be false if object, association pair is not existed' do
39
41
  NPlusOneQuery.add_object_associations(@post, :association1)
40
42
  expect(NPlusOneQuery.association?(@post, :associatio2)).to eq false
41
43
  end
42
44
  end
43
45
 
44
- context ".conditions_met?" do
45
- it "should be true if object is possible, not impossible and object, associations pair is not already existed" do
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
46
48
  allow(NPlusOneQuery).to receive(:possible?).with(@post).and_return(true)
47
49
  allow(NPlusOneQuery).to receive(:impossible?).with(@post).and_return(false)
48
50
  allow(NPlusOneQuery).to receive(:association?).with(@post, :associations).and_return(false)
49
51
  expect(NPlusOneQuery.conditions_met?(@post, :associations)).to eq true
50
52
  end
51
53
 
52
- it "should be false if object is not possible, not impossible and object, associations pair is not already existed" do
54
+ it 'should be false if object is not possible, not impossible and object, associations pair is not already existed' do
53
55
  allow(NPlusOneQuery).to receive(:possible?).with(@post).and_return(false)
54
56
  allow(NPlusOneQuery).to receive(:impossible?).with(@post).and_return(false)
55
57
  allow(NPlusOneQuery).to receive(:association?).with(@post, :associations).and_return(false)
56
58
  expect(NPlusOneQuery.conditions_met?(@post, :associations)).to eq false
57
59
  end
58
60
 
59
- it "should be false if object is possible, but impossible and object, associations pair is not already existed" do
61
+ it 'should be false if object is possible, but impossible and object, associations pair is not already existed' do
60
62
  allow(NPlusOneQuery).to receive(:possible?).with(@post).and_return(true)
61
63
  allow(NPlusOneQuery).to receive(:impossible?).with(@post).and_return(true)
62
64
  allow(NPlusOneQuery).to receive(:association?).with(@post, :associations).and_return(false)
63
65
  expect(NPlusOneQuery.conditions_met?(@post, :associations)).to eq false
64
66
  end
65
67
 
66
- it "should be false if object is possible, not impossible and object, associations pair is already existed" do
68
+ it 'should be false if object is possible, not impossible and object, associations pair is already existed' do
67
69
  allow(NPlusOneQuery).to receive(:possible?).with(@post).and_return(true)
68
70
  allow(NPlusOneQuery).to receive(:impossible?).with(@post).and_return(false)
69
71
  allow(NPlusOneQuery).to receive(:association?).with(@post, :associations).and_return(true)
@@ -71,79 +73,106 @@ module Bullet
71
73
  end
72
74
  end
73
75
 
74
- context ".call_association" do
75
- it "should create notification if conditions met" do
76
+ context '.call_association' do
77
+ it 'should create notification if conditions met' do
76
78
  expect(NPlusOneQuery).to receive(:conditions_met?).with(@post, :association).and_return(true)
77
- expect(NPlusOneQuery).to receive(:caller_in_project).and_return(["caller"])
78
- expect(NPlusOneQuery).to receive(:create_notification).with(["caller"], "Post", :association)
79
+ expect(NPlusOneQuery).to receive(:caller_in_project).and_return(%w[caller])
80
+ expect(NPlusOneQuery).to receive(:create_notification).with(%w[caller], 'Post', :association)
79
81
  NPlusOneQuery.call_association(@post, :association)
80
82
  end
81
83
 
82
- it "should not create notification if conditions not met" do
84
+ it 'should not create notification if conditions not met' do
83
85
  expect(NPlusOneQuery).to receive(:conditions_met?).with(@post, :association).and_return(false)
84
86
  expect(NPlusOneQuery).not_to receive(:caller_in_project!)
85
- expect(NPlusOneQuery).not_to receive(:create_notification).with("Post", :association)
87
+ expect(NPlusOneQuery).not_to receive(:create_notification).with('Post', :association)
86
88
  NPlusOneQuery.call_association(@post, :association)
87
89
  end
88
90
 
89
- context "stacktrace_excludes" do
90
- before { Bullet.stacktrace_excludes = [ /def/ ] }
91
+ context 'stacktrace_excludes' do
92
+ before { Bullet.stacktrace_excludes = [/def/] }
91
93
  after { Bullet.stacktrace_excludes = nil }
92
94
 
93
- it "should not create notification when stacktrace contains paths that are in the exclude list" do
94
- in_project = File.join(Dir.pwd, 'abc', 'abc.rb')
95
- included_path = '/ghi/ghi.rb'
96
- excluded_path = '/def/def.rb'
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)
97
122
 
98
- expect(NPlusOneQuery).to receive(:caller).and_return([in_project, included_path, excluded_path])
123
+ expect(NPlusOneQuery).to receive(:caller_locations).and_return([in_project, excluded_path])
99
124
  expect(NPlusOneQuery).to_not receive(:create_notification)
100
125
  NPlusOneQuery.call_association(@post, :association)
101
126
  end
102
127
  end
103
128
  end
104
129
 
105
- context ".caller_in_project" do
106
- it "should include only paths that are in the project" do
107
- in_project = File.join(Dir.pwd, 'abc', 'abc.rb')
108
- not_in_project = '/def/def.rb'
130
+ context '.caller_in_project' do
131
+ it 'should include only paths that are in the project' do
132
+ in_project = OpenStruct.new(absolute_path: File.join(Dir.pwd, 'abc', 'abc.rb'))
133
+ not_in_project = OpenStruct.new(absolute_path: '/def/def.rb')
109
134
 
110
- expect(NPlusOneQuery).to receive(:caller).and_return([in_project, not_in_project])
135
+ expect(NPlusOneQuery).to receive(:caller_locations).and_return([in_project, not_in_project])
111
136
  expect(NPlusOneQuery).to receive(:conditions_met?).with(@post, :association).and_return(true)
112
- expect(NPlusOneQuery).to receive(:create_notification).with([in_project], "Post", :association)
137
+ expect(NPlusOneQuery).to receive(:create_notification).with([in_project], 'Post', :association)
113
138
  NPlusOneQuery.call_association(@post, :association)
114
139
  end
115
140
 
116
- context "stacktrace_includes" do
117
- before { Bullet.stacktrace_includes = [ 'def', /xyz/ ] }
141
+ context 'stacktrace_includes' do
142
+ before { Bullet.stacktrace_includes = ['def', /xyz/] }
118
143
  after { Bullet.stacktrace_includes = nil }
119
144
 
120
- it "should include paths that are in the stacktrace_include list" do
121
- in_project = File.join(Dir.pwd, 'abc', 'abc.rb')
122
- included_gems = ['/def/def.rb', 'xyz/xyz.rb']
123
- excluded_gem = '/ghi/ghi.rb'
145
+ it 'should include paths that are in the stacktrace_include list' do
146
+ in_project = OpenStruct.new(absolute_path: File.join(Dir.pwd, 'abc', 'abc.rb'))
147
+ included_gems = [OpenStruct.new(absolute_path: '/def/def.rb'), OpenStruct.new(absolute_path: 'xyz/xyz.rb')]
148
+ excluded_gem = OpenStruct.new(absolute_path: '/ghi/ghi.rb')
124
149
 
125
- expect(NPlusOneQuery).to receive(:caller).and_return([in_project, *included_gems, excluded_gem])
150
+ expect(NPlusOneQuery).to receive(:caller_locations).and_return([in_project, *included_gems, excluded_gem])
126
151
  expect(NPlusOneQuery).to receive(:conditions_met?).with(@post, :association).and_return(true)
127
- expect(NPlusOneQuery).to receive(:create_notification).with([in_project, *included_gems], "Post", :association)
152
+ expect(NPlusOneQuery).to receive(:create_notification).with(
153
+ [in_project, *included_gems],
154
+ 'Post',
155
+ :association
156
+ )
128
157
  NPlusOneQuery.call_association(@post, :association)
129
158
  end
130
159
  end
131
160
  end
132
161
 
133
- context ".add_possible_objects" do
134
- it "should add possible objects" do
162
+ context '.add_possible_objects' do
163
+ it 'should add possible objects' do
135
164
  NPlusOneQuery.add_possible_objects([@post, @post2])
136
165
  expect(NPlusOneQuery.possible_objects).to be_include(@post.bullet_key)
137
166
  expect(NPlusOneQuery.possible_objects).to be_include(@post2.bullet_key)
138
167
  end
139
168
 
140
- it "should not raise error if object is nil" do
169
+ it 'should not raise error if object is nil' do
141
170
  expect { NPlusOneQuery.add_possible_objects(nil) }.not_to raise_error
142
171
  end
143
172
  end
144
173
 
145
- context ".add_impossible_object" do
146
- it "should add impossible object" do
174
+ context '.add_impossible_object' do
175
+ it 'should add impossible object' do
147
176
  NPlusOneQuery.add_impossible_object(@post)
148
177
  expect(NPlusOneQuery.impossible_objects).to be_include(@post.bullet_key)
149
178
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  module Bullet
@@ -9,68 +11,85 @@ module Bullet
9
11
  @post3 = Post.last
10
12
  end
11
13
 
12
- context ".call_associations" do
13
- it "should get empty array if eager_loadings" do
14
+ context '.call_associations' do
15
+ it 'should get empty array if eager_loadings' do
14
16
  expect(UnusedEagerLoading.send(:call_associations, @post.bullet_key, Set.new([:association]))).to be_empty
15
17
  end
16
18
 
17
- it "should get call associations if object and association are both in eager_loadings and call_object_associations" do
19
+ it 'should get call associations if object and association are both in eager_loadings and call_object_associations' do
18
20
  UnusedEagerLoading.add_eager_loadings([@post], :association)
19
21
  UnusedEagerLoading.add_call_object_associations(@post, :association)
20
- expect(UnusedEagerLoading.send(:call_associations, @post.bullet_key, Set.new([:association]))).to eq([:association])
22
+ expect(UnusedEagerLoading.send(:call_associations, @post.bullet_key, Set.new([:association]))).to eq(
23
+ [:association]
24
+ )
21
25
  end
22
26
 
23
- it "should not get call associations if not exist in call_object_associations" do
27
+ it 'should not get call associations if not exist in call_object_associations' do
24
28
  UnusedEagerLoading.add_eager_loadings([@post], :association)
25
29
  expect(UnusedEagerLoading.send(:call_associations, @post.bullet_key, Set.new([:association]))).to be_empty
26
30
  end
27
31
  end
28
32
 
29
- context ".diff_object_associations" do
30
- it "should return associations not exist in call_association" do
31
- expect(UnusedEagerLoading.send(:diff_object_associations, @post.bullet_key, Set.new([:association]))).to eq([:association])
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
+ )
32
38
  end
33
39
 
34
- it "should return empty if associations exist in call_association" do
40
+ it 'should return empty if associations exist in call_association' do
35
41
  UnusedEagerLoading.add_eager_loadings([@post], :association)
36
42
  UnusedEagerLoading.add_call_object_associations(@post, :association)
37
- expect(UnusedEagerLoading.send(:diff_object_associations, @post.bullet_key, Set.new([:association]))).to be_empty
43
+ expect(
44
+ UnusedEagerLoading.send(:diff_object_associations, @post.bullet_key, Set.new([:association]))
45
+ ).to be_empty
38
46
  end
39
47
  end
40
48
 
41
- context ".check_unused_preload_associations" do
42
- let(:paths) { ["/dir1", "/dir1/subdir"] }
43
- it "should create notification if object_association_diff is not empty" do
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
44
52
  UnusedEagerLoading.add_object_associations(@post, :association)
45
53
  allow(UnusedEagerLoading).to receive(:caller_in_project).and_return(paths)
46
- expect(UnusedEagerLoading).to receive(:create_notification).with(paths, "Post", [:association])
54
+ expect(UnusedEagerLoading).to receive(:create_notification).with(paths, 'Post', [:association])
47
55
  UnusedEagerLoading.check_unused_preload_associations
48
56
  end
49
57
 
50
- it "should not create notification if object_association_diff is empty" do
58
+ it 'should not create notification if object_association_diff is empty' do
51
59
  UnusedEagerLoading.add_object_associations(@post, :association)
52
60
  UnusedEagerLoading.add_eager_loadings([@post], :association)
53
61
  UnusedEagerLoading.add_call_object_associations(@post, :association)
54
- expect(UnusedEagerLoading.send(:diff_object_associations, @post.bullet_key, Set.new([:association]))).to be_empty
55
- expect(UnusedEagerLoading).not_to receive(:create_notification).with("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])
56
66
  UnusedEagerLoading.check_unused_preload_associations
57
67
  end
58
68
  end
59
69
 
60
- context ".add_eager_loadings" do
61
- it "should add objects, associations pair when eager_loadings are empty" do
70
+ context '.add_eager_loadings' do
71
+ it 'should add objects, associations pair when eager_loadings are empty' do
62
72
  UnusedEagerLoading.add_eager_loadings([@post, @post2], :associations)
63
- expect(UnusedEagerLoading.send(:eager_loadings)).to be_include([@post.bullet_key, @post2.bullet_key], :associations)
73
+ expect(UnusedEagerLoading.send(:eager_loadings)).to be_include(
74
+ [@post.bullet_key, @post2.bullet_key],
75
+ :associations
76
+ )
64
77
  end
65
78
 
66
- it "should add objects, associations pair for existing eager_loadings" do
79
+ it 'should add objects, associations pair for existing eager_loadings' do
67
80
  UnusedEagerLoading.add_eager_loadings([@post, @post2], :association1)
68
81
  UnusedEagerLoading.add_eager_loadings([@post, @post2], :association2)
69
- expect(UnusedEagerLoading.send(:eager_loadings)).to be_include([@post.bullet_key, @post2.bullet_key], :association1)
70
- expect(UnusedEagerLoading.send(:eager_loadings)).to be_include([@post.bullet_key, @post2.bullet_key], :association2)
82
+ expect(UnusedEagerLoading.send(:eager_loadings)).to be_include(
83
+ [@post.bullet_key, @post2.bullet_key],
84
+ :association1
85
+ )
86
+ expect(UnusedEagerLoading.send(:eager_loadings)).to be_include(
87
+ [@post.bullet_key, @post2.bullet_key],
88
+ :association2
89
+ )
71
90
  end
72
91
 
73
- it "should merge objects, associations pair for existing eager_loadings" do
92
+ it 'should merge objects, associations pair for existing eager_loadings' do
74
93
  UnusedEagerLoading.add_eager_loadings([@post], :association1)
75
94
  UnusedEagerLoading.add_eager_loadings([@post, @post2], :association2)
76
95
  expect(UnusedEagerLoading.send(:eager_loadings)).to be_include([@post.bullet_key], :association1)
@@ -78,7 +97,7 @@ module Bullet
78
97
  expect(UnusedEagerLoading.send(:eager_loadings)).to be_include([@post2.bullet_key], :association2)
79
98
  end
80
99
 
81
- it "should vmerge objects recursively, associations pair for existing eager_loadings" do
100
+ it 'should vmerge objects recursively, associations pair for existing eager_loadings' do
82
101
  UnusedEagerLoading.add_eager_loadings([@post, @post2], :association1)
83
102
  UnusedEagerLoading.add_eager_loadings([@post, @post3], :association1)
84
103
  UnusedEagerLoading.add_eager_loadings([@post, @post3], :association2)
@@ -89,7 +108,7 @@ module Bullet
89
108
  expect(UnusedEagerLoading.send(:eager_loadings)).to be_include([@post3.bullet_key], :association2)
90
109
  end
91
110
 
92
- it "should delete objects, associations pair for existing eager_loadings" do
111
+ it 'should delete objects, associations pair for existing eager_loadings' do
93
112
  UnusedEagerLoading.add_eager_loadings([@post, @post2], :association1)
94
113
  UnusedEagerLoading.add_eager_loadings([@post], :association2)
95
114
  expect(UnusedEagerLoading.send(:eager_loadings)).to be_include([@post.bullet_key], :association1)
@@ -1,37 +1,44 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe Object do
4
- context "bullet_key" do
5
- it "should return class and id composition" do
6
+ context 'bullet_key' do
7
+ it 'should return class and id composition' do
6
8
  post = Post.first
7
9
  expect(post.bullet_key).to eq("Post:#{post.id}")
8
10
  end
9
11
 
10
12
  if mongoid?
11
- it "should return class with namesapce and id composition" do
13
+ it 'should return class with namespace and id composition' do
12
14
  post = Mongoid::Post.first
13
15
  expect(post.bullet_key).to eq("Mongoid::Post:#{post.id}")
14
16
  end
15
17
  end
16
18
  end
17
19
 
18
- context "primary_key_value" do
19
- it "should return id" do
20
+ context 'bullet_primary_key_value' do
21
+ it 'should return id' do
20
22
  post = Post.first
21
- expect(post.primary_key_value).to eq(post.id)
23
+ expect(post.bullet_primary_key_value).to eq(post.id)
22
24
  end
23
25
 
24
- it "should return primary key value" do
26
+ it 'should return primary key value' do
25
27
  post = Post.first
26
28
  Post.primary_key = 'name'
27
- expect(post.primary_key_value).to eq(post.name)
29
+ expect(post.bullet_primary_key_value).to eq(post.name)
28
30
  Post.primary_key = 'id'
29
31
  end
30
32
 
31
- it "should return value for multiple primary keys" do
33
+ it 'should return value for multiple primary keys' do
32
34
  post = Post.first
33
- allow(Post).to receive(:primary_keys).and_return([:category_id, :writer_id])
34
- expect(post.primary_key_value).to eq("#{post.category_id},#{post.writer_id}")
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
35
42
  end
36
43
  end
37
44
  end
@@ -1,13 +1,15 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe String do
4
- context "bullet_class_name" do
5
- it "should only return class name" do
6
- expect("Post:1".bullet_class_name).to eq("Post")
6
+ context 'bullet_class_name' do
7
+ it 'should only return class name' do
8
+ expect('Post:1'.bullet_class_name).to eq('Post')
7
9
  end
8
10
 
9
- it "should return class name with namespace" do
10
- expect("Mongoid::Post:1234567890".bullet_class_name).to eq("Mongoid::Post")
11
+ it 'should return class name with namespace' do
12
+ expect('Mongoid::Post:1234567890'.bullet_class_name).to eq('Mongoid::Post')
11
13
  end
12
14
  end
13
15
  end
@@ -1,45 +1,45 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  module Bullet
4
6
  module Notification
5
7
  describe Base do
6
- subject { Base.new(Post, [:comments, :votes]) }
8
+ subject { Base.new(Post, %i[comments votes]) }
7
9
 
8
- context "#title" do
9
- it "should raise NoMethodError" do
10
+ context '#title' do
11
+ it 'should raise NoMethodError' do
10
12
  expect { subject.title }.to raise_error(NoMethodError)
11
13
  end
12
14
  end
13
15
 
14
- context "#body" do
15
- it "should raise NoMethodError" do
16
+ context '#body' do
17
+ it 'should raise NoMethodError' do
16
18
  expect { subject.body }.to raise_error(NoMethodError)
17
19
  end
18
20
  end
19
21
 
20
- context "#whoami" do
21
- it "should display user name" do
22
+ context '#whoami' do
23
+ it 'should display user name' do
22
24
  user = `whoami`.chomp
23
25
  expect(subject.whoami).to eq("user: #{user}")
24
26
  end
25
27
 
26
- it "should leverage ENV parameter" do
27
- temp_env_variable("USER", "bogus") do
28
- expect(subject.whoami).to eq("user: bogus")
29
- end
28
+ it 'should leverage ENV parameter' do
29
+ temp_env_variable('USER', 'bogus') { expect(subject.whoami).to eq('user: bogus') }
30
30
  end
31
31
 
32
- it "should return blank if no user available" do
33
- temp_env_variable("USER", "") do
34
- expect(subject).to receive(:`).with("whoami").and_return("")
35
- expect(subject.whoami).to eq("")
32
+ it 'should return blank if no user available' do
33
+ temp_env_variable('USER', '') do
34
+ expect(subject).to receive(:`).with('whoami').and_return('')
35
+ expect(subject.whoami).to eq('')
36
36
  end
37
37
  end
38
38
 
39
- it "should return blank if whoami is not available" do
40
- temp_env_variable("USER", "") do
41
- expect(subject).to receive(:`).with("whoami").and_raise(Errno::ENOENT)
42
- expect(subject.whoami).to eq("")
39
+ it 'should return blank if whoami is not available' do
40
+ temp_env_variable('USER', '') do
41
+ expect(subject).to receive(:`).with('whoami').and_raise(Errno::ENOENT)
42
+ expect(subject.whoami).to eq('')
43
43
  end
44
44
  end
45
45
 
@@ -50,43 +50,42 @@ module Bullet
50
50
  ensure
51
51
  ENV[name] = old_value
52
52
  end
53
-
54
53
  end
55
54
 
56
- context "#body_with_caller" do
57
- it "should return body" do
58
- allow(subject).to receive(:body).and_return("body")
59
- allow(subject).to receive(:call_stack_messages).and_return("call_stack_messages")
55
+ context '#body_with_caller' do
56
+ it 'should return body' do
57
+ allow(subject).to receive(:body).and_return('body')
58
+ allow(subject).to receive(:call_stack_messages).and_return('call_stack_messages')
60
59
  expect(subject.body_with_caller).to eq("body\ncall_stack_messages\n")
61
60
  end
62
61
  end
63
62
 
64
- context "#notification_data" do
65
- it "should return notification data" do
66
- allow(subject).to receive(:whoami).and_return("whoami")
67
- allow(subject).to receive(:url).and_return("url")
68
- allow(subject).to receive(:title).and_return("title")
69
- allow(subject).to receive(:body_with_caller).and_return("body_with_caller")
70
- expect(subject.notification_data).to eq(:user => "whoami", :url => "url", :title => "title", :body => "body_with_caller")
63
+ context '#notification_data' do
64
+ it 'should return notification data' do
65
+ allow(subject).to receive(:whoami).and_return('whoami')
66
+ allow(subject).to receive(:url).and_return('url')
67
+ allow(subject).to receive(:title).and_return('title')
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')
71
70
  end
72
71
  end
73
72
 
74
- context "#notify_inline" do
75
- it "should send full_notice to notifier" do
73
+ context '#notify_inline' do
74
+ it 'should send full_notice to notifier' do
76
75
  notifier = double
77
76
  allow(subject).to receive(:notifier).and_return(notifier)
78
- allow(subject).to receive(:notification_data).and_return(:foo => :bar)
79
- 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)
80
79
  subject.notify_inline
81
80
  end
82
81
  end
83
82
 
84
- context "#notify_out_of_channel" do
85
- it "should send full_out_of_channel to notifier" do
83
+ context '#notify_out_of_channel' do
84
+ it 'should send full_out_of_channel to notifier' do
86
85
  notifier = double
87
86
  allow(subject).to receive(:notifier).and_return(notifier)
88
- allow(subject).to receive(:notification_data).and_return(:foo => :bar)
89
- 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)
90
89
  subject.notify_out_of_channel
91
90
  end
92
91
  end
@@ -1,12 +1,14 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  module Bullet
4
6
  module Notification
5
7
  describe CounterCache do
6
- subject { CounterCache.new(Post, [:comments, :votes]) }
8
+ subject { CounterCache.new(Post, %i[comments votes]) }
7
9
 
8
- it { expect(subject.body).to eq(" Post => [:comments, :votes]") }
9
- it { expect(subject.title).to eq("Need Counter Cache") }
10
+ it { expect(subject.body).to eq(' Post => [:comments, :votes]') }
11
+ it { expect(subject.title).to eq('Need Counter Cache') }
10
12
  end
11
13
  end
12
14
  end
@@ -1,14 +1,29 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  module Bullet
4
6
  module Notification
5
7
  describe NPlusOneQuery do
6
- subject { NPlusOneQuery.new([["caller1", "caller2"]], Post, [:comments, :votes], "path") }
8
+ subject { NPlusOneQuery.new([%w[caller1 caller2]], Post, %i[comments votes], 'path') }
7
9
 
8
- it { expect(subject.body_with_caller).to eq(" Post => [:comments, :votes]\n Add to your finder: :includes => [:comments, :votes]\nCall stack\n caller1\n caller2\n") }
9
- it { expect([subject.body_with_caller, subject.body_with_caller]).to eq([ " Post => [:comments, :votes]\n Add to your finder: :includes => [:comments, :votes]\nCall stack\n caller1\n caller2\n", " Post => [:comments, :votes]\n Add to your finder: :includes => [:comments, :votes]\nCall stack\n caller1\n caller2\n" ]) }
10
- it { expect(subject.body).to eq(" Post => [:comments, :votes]\n Add to your finder: :includes => [:comments, :votes]") }
11
- it { expect(subject.title).to eq("USE eager loading in path") }
10
+ it do
11
+ expect(subject.body_with_caller).to eq(
12
+ " Post => [:comments, :votes]\n Add to your query: .includes([:comments, :votes])\nCall stack\n caller1\n caller2\n"
13
+ )
14
+ end
15
+ it do
16
+ expect([subject.body_with_caller, subject.body_with_caller]).to eq(
17
+ [
18
+ " Post => [:comments, :votes]\n Add to your query: .includes([:comments, :votes])\nCall stack\n caller1\n caller2\n",
19
+ " Post => [:comments, :votes]\n Add to your query: .includes([:comments, :votes])\nCall stack\n caller1\n caller2\n"
20
+ ]
21
+ )
22
+ end
23
+ it do
24
+ expect(subject.body).to eq(" Post => [:comments, :votes]\n Add to your query: .includes([:comments, :votes])")
25
+ end
26
+ it { expect(subject.title).to eq('USE eager loading in path') }
12
27
  end
13
28
  end
14
29
  end
@@ -1,12 +1,18 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  module Bullet
4
6
  module Notification
5
7
  describe UnusedEagerLoading do
6
- subject { UnusedEagerLoading.new([""], Post, [:comments, :votes], "path") }
8
+ subject { UnusedEagerLoading.new([''], Post, %i[comments votes], 'path') }
7
9
 
8
- it { expect(subject.body).to eq(" Post => [:comments, :votes]\n Remove from your finder: :includes => [:comments, :votes]") }
9
- it { expect(subject.title).to eq("AVOID eager loading in path") }
10
+ it do
11
+ expect(subject.body).to eq(
12
+ " Post => [:comments, :votes]\n Remove from your query: .includes([:comments, :votes])"
13
+ )
14
+ end
15
+ it { expect(subject.title).to eq('AVOID eager loading in path') }
10
16
  end
11
17
  end
12
18
  end