bullet 5.5.1 → 5.6.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: '06945d7fd724e3e1f6355de32b078fac99e6366a'
4
- data.tar.gz: ab28a1e628416d945ec40ad21b0ff3e8e4dd50ac
3
+ metadata.gz: 652f59b5a91224c16cace3931e368d0da02fa449
4
+ data.tar.gz: 9ef371969315cd308b194a9d230d1f19892a57e4
5
5
  SHA512:
6
- metadata.gz: 33e0206bd7d7624e3ca311f48274708fcc8030a23ec77954007faaa6b2b14b1d4fd3a7f75c18a8150399565770dd19e252856c2cc94907c6abd3147488280bbf
7
- data.tar.gz: cac678c258a0d278c92cbff1bb5e820d9ec71d628a55573588d3fb100a2ded60d28e496c7906632d438f367835d41b923aa98828028693183610840a22c5d114
6
+ metadata.gz: ed473ab951e1f168de703cf0615f203abc93e37ef896330d6f91c7b61d320cd0906e691e41245e13a11aa9e3aa3d059ea62b00b256fa96af0540c8ab35ebc2fb
7
+ data.tar.gz: f6c4456dfb56957b441fce1b56094baacc911186b59b48b43f22e41ad3bbed88c52aa16b4bc7247b7ca37a3c7d026bb45f5342ccc24b37bc47836cd63fb41a1c
@@ -8,10 +8,5 @@ gemfile:
8
8
  - Gemfile.rails-4.2
9
9
  - Gemfile.rails-4.1
10
10
  - Gemfile.rails-4.0
11
- - Gemfile.mongoid-6.0
12
- - Gemfile.mongoid-5.0
13
- - Gemfile.mongoid-4.0
14
11
  env:
15
12
  - DB=sqlite
16
- services:
17
- - mongodb
@@ -1,10 +1,13 @@
1
1
  # Next Release
2
2
 
3
- ## 5.5.1 (03/01/2016)
3
+ ## 5.6.0 (07/16/2017)
4
4
 
5
+ * Migrate alias_method to Module#prepend
6
+ * Add install generator
7
+ * Stack trace filter
8
+ * Fix rails 5.1 compatibility
5
9
  * Fix inverse_of for rails 5
6
10
  * Fix detect file attachment for rack #319
7
- * Fix `ActiveRecord::Associations::SingularAssociation#reader` usage for Rails 5.1
8
11
 
9
12
  ## 5.5.0 (12/30/2016)
10
13
 
data/Gemfile CHANGED
@@ -1,8 +1,13 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
+ git_source(:github) do |repo_name|
4
+ repo_name = "#{repo_name}/#{repo_name}" unless repo_name.include?('/')
5
+ "https://github.com/#{repo_name}.git"
6
+ end
7
+
3
8
  gemspec
4
9
 
5
- gem 'rails', github: 'rails/rails'
10
+ gem 'rails', github: 'rails'
6
11
  gem 'sqlite3', platforms: [:ruby]
7
12
  gem 'activerecord-jdbcsqlite3-adapter', platforms: [:jruby]
8
13
  gem 'activerecord-import'
@@ -2,7 +2,7 @@ source "https://rubygems.org"
2
2
 
3
3
  gemspec
4
4
 
5
- gem 'rails', '5.0.0'
5
+ gem 'rails', '~> 5.0.0'
6
6
  gem 'sqlite3'
7
7
  gem 'activerecord-jdbcsqlite3-adapter', platforms: [:jruby]
8
8
  gem 'activerecord-import'
@@ -2,7 +2,7 @@ source "https://rubygems.org"
2
2
 
3
3
  gemspec
4
4
 
5
- gem 'rails', '5.1.0.beta.1'
5
+ gem 'rails', '~> 5.1.0'
6
6
  gem 'sqlite3'
7
7
  gem 'activerecord-jdbcsqlite3-adapter', platforms: [:jruby]
8
8
  gem 'activerecord-import'
data/README.md CHANGED
@@ -303,19 +303,10 @@ And run
303
303
  bundle install
304
304
  ```
305
305
 
306
- 6\. enable the Bullet gem in development, add a line to
307
- `config/environments/development.rb`
306
+ 6\. enable the Bullet gem with generate command
308
307
 
309
- ```ruby
310
- config.after_initialize do
311
- Bullet.enable = true
312
- Bullet.alert = true
313
- Bullet.bullet_logger = true
314
- Bullet.console = true
315
- # Bullet.growl = true
316
- Bullet.rails_logger = true
317
- Bullet.add_footer = true
318
- end
308
+ ```
309
+ bundle exec rails g bullet:install
319
310
  ```
320
311
 
321
312
  7\. Start the server
@@ -18,38 +18,34 @@ module Bullet
18
18
  module ActiveRecord
19
19
  def self.enable
20
20
  require 'active_record'
21
- ::ActiveRecord::Base.class_eval do
22
- class <<self
23
- alias_method :origin_find_by_sql, :find_by_sql
24
- def find_by_sql(sql, binds = [], preparable: nil, &block)
25
- result = origin_find_by_sql(sql, binds, preparable: nil, &block)
26
- if Bullet.start?
27
- if result.is_a? Array
28
- if result.size > 1
29
- Bullet::Detector::NPlusOneQuery.add_possible_objects(result)
30
- Bullet::Detector::CounterCache.add_possible_objects(result)
31
- elsif result.size == 1
32
- Bullet::Detector::NPlusOneQuery.add_impossible_object(result.first)
33
- Bullet::Detector::CounterCache.add_impossible_object(result.first)
34
- end
35
- elsif result.is_a? ::ActiveRecord::Base
36
- Bullet::Detector::NPlusOneQuery.add_impossible_object(result)
37
- Bullet::Detector::CounterCache.add_impossible_object(result)
21
+ ::ActiveRecord::Base.extend(Module.new {
22
+ def find_by_sql(sql, binds = [], preparable: nil, &block)
23
+ result = super
24
+ if Bullet.start?
25
+ if result.is_a? Array
26
+ if result.size > 1
27
+ Bullet::Detector::NPlusOneQuery.add_possible_objects(result)
28
+ Bullet::Detector::CounterCache.add_possible_objects(result)
29
+ elsif result.size == 1
30
+ Bullet::Detector::NPlusOneQuery.add_impossible_object(result.first)
31
+ Bullet::Detector::CounterCache.add_impossible_object(result.first)
38
32
  end
33
+ elsif result.is_a? ::ActiveRecord::Base
34
+ Bullet::Detector::NPlusOneQuery.add_impossible_object(result)
35
+ Bullet::Detector::CounterCache.add_impossible_object(result)
39
36
  end
40
- result
41
37
  end
38
+ result
42
39
  end
43
- end
40
+ })
44
41
 
45
42
  ::ActiveRecord::Base.prepend(SaveWithBulletSupport)
46
43
 
47
- ::ActiveRecord::Relation.class_eval do
48
- alias_method :origin_records, :records
44
+ ::ActiveRecord::Relation.prepend(Module.new {
49
45
  # if select a collection of objects, then these objects have possible to cause N+1 query.
50
46
  # if select only one object, then the only one object has impossible to cause N+1 query.
51
47
  def records
52
- result = origin_records
48
+ result = super
53
49
  if Bullet.start?
54
50
  if result.first.class.name !~ /^HABTM_/
55
51
  if result.size > 1
@@ -63,11 +59,9 @@ module Bullet
63
59
  end
64
60
  result
65
61
  end
66
- end
67
-
68
- ::ActiveRecord::Associations::Preloader.class_eval do
69
- alias_method :origin_preloaders_for_one, :preloaders_for_one
62
+ })
70
63
 
64
+ ::ActiveRecord::Associations::Preloader.prepend(Module.new {
71
65
  def preloaders_for_one(association, records, scope)
72
66
  if Bullet.start?
73
67
  records.compact!
@@ -78,16 +72,15 @@ module Bullet
78
72
  Bullet::Detector::UnusedEagerLoading.add_eager_loadings(records, association)
79
73
  end
80
74
  end
81
- origin_preloaders_for_one(association, records, scope)
75
+ super
82
76
  end
83
- end
77
+ })
84
78
 
85
- ::ActiveRecord::FinderMethods.class_eval do
79
+ ::ActiveRecord::FinderMethods.prepend(Module.new {
86
80
  # add includes in scope
87
- alias_method :origin_find_with_associations, :find_with_associations
88
81
  def find_with_associations
89
- return origin_find_with_associations { |r| yield r } if block_given?
90
- records = origin_find_with_associations
82
+ return super { |r| yield r } if block_given?
83
+ records = super
91
84
  if Bullet.start?
92
85
  associations = (eager_load_values + includes_values).uniq
93
86
  records.each do |record|
@@ -97,16 +90,12 @@ module Bullet
97
90
  end
98
91
  records
99
92
  end
100
- end
101
-
102
- ::ActiveRecord::Associations::JoinDependency.class_eval do
103
- alias_method :origin_instantiate, :instantiate
104
- alias_method :origin_construct, :construct
105
- alias_method :origin_construct_model, :construct_model
93
+ })
106
94
 
95
+ ::ActiveRecord::Associations::JoinDependency.prepend(Module.new {
107
96
  def instantiate(result_set, aliases)
108
97
  @bullet_eager_loadings = {}
109
- records = origin_instantiate(result_set, aliases)
98
+ records = super
110
99
 
111
100
  if Bullet.start?
112
101
  @bullet_eager_loadings.each do |klazz, eager_loadings_hash|
@@ -135,12 +124,12 @@ module Bullet
135
124
  end
136
125
  end
137
126
 
138
- origin_construct(ar_parent, parent, row, rs, seen, model_cache, aliases)
127
+ super
139
128
  end
140
129
 
141
130
  # call join associations
142
131
  def construct_model(record, node, row, model_cache, id, aliases)
143
- result = origin_construct_model(record, node, row, model_cache, id, aliases)
132
+ result = super
144
133
 
145
134
  if Bullet.start?
146
135
  associations = node.reflection.name
@@ -153,13 +142,11 @@ module Bullet
153
142
 
154
143
  result
155
144
  end
156
- end
145
+ })
157
146
 
158
- ::ActiveRecord::Associations::CollectionAssociation.class_eval do
159
- # call one to many associations
160
- alias_method :origin_load_target, :load_target
147
+ ::ActiveRecord::Associations::CollectionAssociation.prepend(Module.new {
161
148
  def load_target
162
- records = origin_load_target
149
+ records = super
163
150
 
164
151
  if Bullet.start?
165
152
  if self.is_a? ::ActiveRecord::Associations::ThroughAssociation
@@ -183,28 +170,25 @@ module Bullet
183
170
  records
184
171
  end
185
172
 
186
- alias_method :origin_empty?, :empty?
187
173
  def empty?
188
174
  if Bullet.start? && !reflection.has_cached_counter?
189
175
  Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name)
190
176
  end
191
- origin_empty?
177
+ super
192
178
  end
193
179
 
194
- alias_method :origin_include?, :include?
195
180
  def include?(object)
196
181
  if Bullet.start?
197
182
  Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name)
198
183
  end
199
- origin_include?(object)
184
+ super
200
185
  end
201
- end
186
+ })
202
187
 
203
- ::ActiveRecord::Associations::SingularAssociation.class_eval do
188
+ ::ActiveRecord::Associations::SingularAssociation.prepend(Module.new {
204
189
  # call has_one and belongs_to associations
205
- alias_method :origin_reader, :reader
206
- def reader(force_reload = false)
207
- result = force_reload ? force_reload_reader : origin_reader
190
+ def target
191
+ result = super()
208
192
  if Bullet.start?
209
193
  if owner.class.name !~ /^HABTM_/ && !@inversed
210
194
  Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name)
@@ -217,27 +201,25 @@ module Bullet
217
201
  end
218
202
  result
219
203
  end
220
- end
204
+ })
221
205
 
222
- ::ActiveRecord::Associations::HasManyAssociation.class_eval do
223
- alias_method :origin_many_empty?, :empty?
206
+ ::ActiveRecord::Associations::HasManyAssociation.prepend(Module.new {
224
207
  def empty?
225
- result = origin_many_empty?
208
+ result = super
226
209
  if Bullet.start? && !reflection.has_cached_counter?
227
210
  Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name)
228
211
  end
229
212
  result
230
213
  end
231
214
 
232
- alias_method :origin_count_records, :count_records
233
215
  def count_records
234
216
  result = reflection.has_cached_counter?
235
217
  if Bullet.start? && !result && !self.is_a?(::ActiveRecord::Associations::ThroughAssociation)
236
218
  Bullet::Detector::CounterCache.add_counter_cache(owner, reflection.name)
237
219
  end
238
- origin_count_records
220
+ super
239
221
  end
240
- end
222
+ })
241
223
  end
242
224
  end
243
225
  end
@@ -7,7 +7,7 @@ module Bullet
7
7
  return if !Bullet.n_plus_one_query_enable? && !Bullet.unused_eager_loading_enable?
8
8
  return unless object.primary_key_value
9
9
 
10
- Bullet.debug("Detector::Association#add_object_associations", "object: #{object.bullet_key}, associations: #{associations}")
10
+ Bullet.debug("Detector::Association#add_object_associations".freeze, "object: #{object.bullet_key}, associations: #{associations}")
11
11
  object_associations.add(object.bullet_key, associations)
12
12
  end
13
13
 
@@ -16,7 +16,7 @@ module Bullet
16
16
  return if !Bullet.n_plus_one_query_enable? && !Bullet.unused_eager_loading_enable?
17
17
  return unless object.primary_key_value
18
18
 
19
- Bullet.debug("Detector::Association#add_call_object_associations", "object: #{object.bullet_key}, associations: #{associations}")
19
+ Bullet.debug("Detector::Association#add_call_object_associations".freeze, "object: #{object.bullet_key}, associations: #{associations}")
20
20
  call_object_associations.add(object.bullet_key, associations)
21
21
  end
22
22
 
@@ -16,7 +16,7 @@ module Bullet
16
16
  return if inversed_objects.include?(object.bullet_key, associations)
17
17
  add_call_object_associations(object, associations)
18
18
 
19
- Bullet.debug("Detector::NPlusOneQuery#call_association", "object: #{object.bullet_key}, associations: #{associations}")
19
+ Bullet.debug("Detector::NPlusOneQuery#call_association".freeze, "object: #{object.bullet_key}, associations: #{associations}")
20
20
  if !excluded_stacktrace_path? && conditions_met?(object, associations)
21
21
  Bullet.debug("detect n + 1 query", "object: #{object.bullet_key}, associations: #{associations}")
22
22
  create_notification caller_in_project, object.class.to_s, associations
@@ -29,7 +29,7 @@ module Bullet
29
29
  objects = Array(object_or_objects)
30
30
  return if objects.map(&:primary_key_value).compact.empty?
31
31
 
32
- Bullet.debug("Detector::NPlusOneQuery#add_possible_objects", "objects: #{objects.map(&:bullet_key).join(', ')}")
32
+ Bullet.debug("Detector::NPlusOneQuery#add_possible_objects".freeze, "objects: #{objects.map(&:bullet_key).join(', '.freeze)}")
33
33
  objects.each { |object| possible_objects.add object.bullet_key }
34
34
  end
35
35
 
@@ -38,7 +38,7 @@ module Bullet
38
38
  return unless Bullet.n_plus_one_query_enable?
39
39
  return unless object.primary_key_value
40
40
 
41
- Bullet.debug("Detector::NPlusOneQuery#add_impossible_object", "object: #{object.bullet_key}")
41
+ Bullet.debug("Detector::NPlusOneQuery#add_impossible_object".freeze, "object: #{object.bullet_key}")
42
42
  impossible_objects.add object.bullet_key
43
43
  end
44
44
 
@@ -47,7 +47,7 @@ module Bullet
47
47
  return unless Bullet.n_plus_one_query_enable?
48
48
  return unless object.primary_key_value
49
49
 
50
- Bullet.debug("Detector::NPlusOneQuery#add_inversed_object", "object: #{object.bullet_key}, association: #{association}")
50
+ Bullet.debug("Detector::NPlusOneQuery#add_inversed_object".freeze, "object: #{object.bullet_key}, association: #{association}")
51
51
  inversed_objects.add object.bullet_key, association
52
52
  end
53
53
 
@@ -5,7 +5,7 @@ class Object
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(',')
8
+ self.class.primary_keys.map { |primary_key| self.send primary_key }.join(','.freeze)
9
9
  elsif self.class.respond_to?(:primary_key) && self.class.primary_key
10
10
  self.send self.class.primary_key
11
11
  else
@@ -1,5 +1,5 @@
1
1
  class String
2
2
  def bullet_class_name
3
- self.sub(/:[^:]*?$/, "")
3
+ self.sub(/:[^:]*?$/, "".freeze)
4
4
  end
5
5
  end
@@ -66,7 +66,7 @@ module Bullet
66
66
 
67
67
  protected
68
68
  def klazz_associations_str
69
- " #{@base_class} => [#{@associations.map(&:inspect).join(', ')}]"
69
+ " #{@base_class} => [#{@associations.map(&:inspect).join(', '.freeze)}]"
70
70
  end
71
71
 
72
72
  def associations_str
@@ -5,7 +5,8 @@ module Bullet
5
5
  def caller_in_project
6
6
  app_root = rails? ? Rails.root.to_s : Dir.pwd
7
7
  vendor_root = app_root + VENDOR_PATH
8
- caller.select do |caller_path|
8
+ caller_locations.select do |location|
9
+ caller_path = location.absolute_path
9
10
  caller_path.include?(app_root) && !caller_path.include?(vendor_root) ||
10
11
  Bullet.stacktrace_includes.any? do |include_pattern|
11
12
  case include_pattern
@@ -1,4 +1,4 @@
1
1
  # encoding: utf-8
2
2
  module Bullet
3
- VERSION = "5.5.1"
3
+ VERSION = "5.6.0"
4
4
  end
@@ -0,0 +1,46 @@
1
+ module Bullet
2
+ module Generators
3
+ class InstallGenerator < ::Rails::Generators::Base
4
+ desc <<-DESC
5
+ Description:
6
+ Enable bullet in development/test for your application.
7
+ DESC
8
+
9
+ def enable_in_development
10
+ environment(nil, env: "development") do
11
+ <<-"FILE".strip
12
+
13
+ config.after_initialize do
14
+ Bullet.enable = true
15
+ Bullet.alert = true
16
+ Bullet.bullet_logger = true
17
+ Bullet.console = true
18
+ # Bullet.growl = true
19
+ Bullet.rails_logger = true
20
+ Bullet.add_footer = true
21
+ end
22
+ FILE
23
+ end
24
+
25
+ say "Enabled bullet in config/environments/development.rb"
26
+ end
27
+
28
+ def enable_in_test
29
+ if yes?("Would you like to enable bullet in test environment? (y/n)")
30
+ environment(nil, env: "test") do
31
+ <<-"FILE".strip
32
+
33
+ config.after_initialize do
34
+ Bullet.enable = true
35
+ Bullet.bullet_logger = true
36
+ Bullet.raise = true # raise an error if n+1 query occurs
37
+ end
38
+ FILE
39
+ end
40
+
41
+ say "Enabled bullet in config/environments/test.rb"
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -91,11 +91,11 @@ 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 = File.join(Dir.pwd, 'abc', 'abc.rb')
95
- included_path = '/ghi/ghi.rb'
96
- excluded_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
- expect(NPlusOneQuery).to receive(:caller).and_return([in_project, included_path, excluded_path])
98
+ expect(NPlusOneQuery).to receive(:caller_locations).and_return([in_project, included_path, excluded_path])
99
99
  expect(NPlusOneQuery).to_not receive(:create_notification)
100
100
  NPlusOneQuery.call_association(@post, :association)
101
101
  end
@@ -104,10 +104,10 @@ 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 = File.join(Dir.pwd, 'abc', 'abc.rb')
108
- not_in_project = '/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
- expect(NPlusOneQuery).to receive(:caller).and_return([in_project, not_in_project])
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)
112
112
  expect(NPlusOneQuery).to receive(:create_notification).with([in_project], "Post", :association)
113
113
  NPlusOneQuery.call_association(@post, :association)
@@ -118,11 +118,11 @@ 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 = File.join(Dir.pwd, 'abc', 'abc.rb')
122
- included_gems = ['/def/def.rb', 'xyz/xyz.rb']
123
- excluded_gem = '/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
- expect(NPlusOneQuery).to receive(:caller).and_return([in_project, *included_gems, excluded_gem])
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)
127
127
  expect(NPlusOneQuery).to receive(:create_notification).with([in_project, *included_gems], "Post", :association)
128
128
  NPlusOneQuery.call_association(@post, :association)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bullet
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.5.1
4
+ version: 5.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Richard Huang
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-03-01 00:00:00.000000000 Z
11
+ date: 2017-07-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -95,6 +95,7 @@ files:
95
95
  - lib/bullet/registry/object.rb
96
96
  - lib/bullet/stack_trace_filter.rb
97
97
  - lib/bullet/version.rb
98
+ - lib/generators/bullet/install_generator.rb
98
99
  - perf/benchmark.rb
99
100
  - rails/init.rb
100
101
  - spec/bullet/detector/association_spec.rb
@@ -177,7 +178,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
177
178
  version: 1.3.6
178
179
  requirements: []
179
180
  rubyforge_project:
180
- rubygems_version: 2.5.2
181
+ rubygems_version: 2.6.12
181
182
  signing_key:
182
183
  specification_version: 4
183
184
  summary: help to kill N+1 queries and unused eager loading.