flyerhzm-bullet 1.4.0 → 1.4.1

Sign up to get free protection for your applications and to get access to all the features.
data/README.textile CHANGED
@@ -9,6 +9,7 @@ Best practice is to use Bullet in development mode or custom mode (staging, prof
9
9
  h2. Thanks
10
10
 
11
11
  flipsasser added Growl, console.log and Rails.log support, very awesome. And he improved README.
12
+ rainux add group style console.log.
12
13
 
13
14
  ****************************************************************************
14
15
 
@@ -97,6 +98,22 @@ To get Growl support up-and-running for Bullet, follow the steps below:
97
98
 
98
99
  ****************************************************************************
99
100
 
101
+ h2. Advance
102
+
103
+ The bullet plugin use rack middleware for http request. If you want to bullet for without http server, such as job server. You can do like this:
104
+
105
+ <pre><code>
106
+ Bullet::Association.start_request if Bullet.enable?
107
+ # run job
108
+ if Bullet.enable?
109
+ Bullet::Association.growl_notification
110
+ Bullet::Association.log_notificatioin('JobServer: ')
111
+ Bullet::Association.end_request
112
+ end
113
+ </code></pre>
114
+
115
+ ****************************************************************************
116
+
100
117
  h2. Step by step example
101
118
 
102
119
  Bullet is designed to function as you browse through your application in development. It will alert you whenever it encounters N+1 queries or unused eager loading.
data/Rakefile CHANGED
@@ -17,7 +17,7 @@ end
17
17
 
18
18
  desc "Run all specs in spec directory"
19
19
  Spec::Rake::SpecTask.new(:spec) do |t|
20
- t.spec_files = FileList['spec/spec_helper.rb', 'spec/**/*_spec.rb']
20
+ t.spec_files = FileList['spec/**/*_spec.rb']
21
21
  end
22
22
 
23
23
  Jeweler::Tasks.new do |gemspec|
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.4.0
1
+ 1.4.1
data/bullet.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{bullet}
8
- s.version = "1.4.0"
8
+ s.version = "1.4.1"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Richard Huang"]
12
- s.date = %q{2009-09-03}
12
+ s.date = %q{2009-09-09}
13
13
  s.description = %q{The Bullet plugin is designed to help you increase your application's performance by reducing the number of queries it makes. It will watch your queries while you develop your application and notify you when you should add eager loading (N+1 queries) or when you're using eager loading that isn't necessary.}
14
14
  s.email = %q{flyerhzm@gmail.com}
15
15
  s.extra_rdoc_files = [
@@ -24,10 +24,12 @@ Gem::Specification.new do |s|
24
24
  "lib/bullet.rb",
25
25
  "lib/bullet/active_record.rb",
26
26
  "lib/bullet/association.rb",
27
+ "lib/bullet/counter.rb",
27
28
  "lib/bullet/logger.rb",
28
29
  "lib/bulletware.rb",
29
30
  "rails/init.rb",
30
31
  "spec/bullet_association_spec.rb",
32
+ "spec/bullet_counter_spec.rb",
31
33
  "spec/spec.opts",
32
34
  "spec/spec_helper.rb",
33
35
  "tasks/bullet_tasks.rake"
@@ -39,6 +41,7 @@ Gem::Specification.new do |s|
39
41
  s.summary = %q{A plugin to kill N+1 queries and unused eager loading}
40
42
  s.test_files = [
41
43
  "spec/bullet_association_spec.rb",
44
+ "spec/bullet_counter_spec.rb",
42
45
  "spec/spec_helper.rb"
43
46
  ]
44
47
 
data/lib/bullet.rb CHANGED
@@ -1,3 +1,5 @@
1
+ require 'bulletware'
2
+
1
3
  module Bullet
2
4
  @@enable = nil
3
5
 
@@ -62,6 +62,15 @@ module Bullet
62
62
  origin_load_target
63
63
  end
64
64
  end
65
+
66
+ ::ActiveRecord::Associations::HasManyAssociation.class_eval do
67
+ alias_method :origin_has_cached_counter?, :has_cached_counter?
68
+ def has_cached_counter?
69
+ result = origin_has_cached_counter?
70
+ Bullet::Counter.add_counter_cache(@owner, @reflection.name) unless result
71
+ result
72
+ end
73
+ end
65
74
  end
66
75
  end
67
76
  end
@@ -11,33 +11,13 @@ module Bullet
11
11
  @@growl_password = nil
12
12
  @@rails_logger = nil
13
13
 
14
- def start_request
15
- # puts "start request"
16
- end
17
-
18
- def end_request
19
- # puts "end request"
20
- @@object_associations = nil
21
- @@unpreload_associations = nil
22
- @@unused_preload_associations = nil
23
- @@callers = nil
24
- @@possible_objects = nil
25
- @@impossible_objects = nil
26
- @@call_object_associations = nil
27
- @@eager_loadings = nil
28
- end
29
-
14
+ ###################################################
15
+ # Configurations
16
+ ###################################################
30
17
  def alert=(alert)
31
18
  @@alert = alert
32
19
  end
33
20
 
34
- def bullet_logger=(bullet_logger)
35
- if @@bullet_logger = bullet_logger
36
- @@logger_file = File.open(Bullet::BulletLogger::LOG_FILE, 'a+')
37
- @@logger = Bullet::BulletLogger.new(@@logger_file)
38
- end
39
- end
40
-
41
21
  def console=(console)
42
22
  @@console = console
43
23
  end
@@ -59,32 +39,44 @@ module Bullet
59
39
  @@growl_password = growl_password
60
40
  end
61
41
 
42
+ def bullet_logger=(bullet_logger)
43
+ if @@bullet_logger = bullet_logger
44
+ @@logger_file = File.open(Bullet::BulletLogger::LOG_FILE, 'a+')
45
+ @@logger = Bullet::BulletLogger.new(@@logger_file)
46
+ end
47
+ end
48
+
62
49
  def rails_logger=(rails_logger)
63
50
  @@rails_logger = rails_logger
64
51
  end
65
52
 
66
- def check_unused_preload_associations
67
- object_associations.each do |object, association|
68
- related_objects = eager_loadings.select {|key, value| key.include?(object) and value == association}.collect(&:first).flatten
69
- call_object_association = related_objects.collect { |related_object| call_object_associations[related_object] }.compact.flatten.uniq
70
- diff_object_association = (association - call_object_association).reject {|a| a.is_a? Hash}
71
- add_unused_preload_associations(object.class, diff_object_association) unless diff_object_association.empty?
72
- end
53
+ #####################################################
54
+ # login control interface
55
+ #####################################################
56
+ def start_request
57
+ # puts "start request"
73
58
  end
74
-
59
+
60
+ def end_request
61
+ # puts "end request"
62
+ @@object_associations = nil
63
+ @@unpreload_associations = nil
64
+ @@unused_preload_associations = nil
65
+ @@callers = nil
66
+ @@possible_objects = nil
67
+ @@impossible_objects = nil
68
+ @@call_object_associations = nil
69
+ @@eager_loadings = nil
70
+ end
71
+
75
72
  def has_bad_assocations?
76
73
  check_unused_preload_associations
77
74
  has_unpreload_associations? or has_unused_preload_associations?
78
75
  end
79
76
 
80
- def has_unused_preload_associations?
81
- !unused_preload_associations.empty?
82
- end
83
-
84
- def has_unpreload_associations?
85
- !unpreload_associations.empty?
86
- end
87
-
77
+ ######################################################
78
+ # Notifications
79
+ ######################################################
88
80
  def javascript_notification
89
81
  str = ''
90
82
  if @@alert || @@console
@@ -94,11 +86,30 @@ module Bullet
94
86
  str << wrap_js_association("alert(#{response.join("\n").inspect});")
95
87
  end
96
88
  if @@console
97
- str << wrap_js_association("if (typeof(console) != 'undefined' && console.log) console.log(#{response.join("\n").inspect});")
89
+ title = []
90
+ title << unused_preload_messages.first.first unless unused_preload_messages.empty?
91
+ title << unpreload_messages.first.first unless unpreload_messages.empty?
92
+ code = <<-CODE
93
+ if (typeof(console) !== 'undefined') {
94
+
95
+ if (console.groupCollapsed && console.groupEnd && console.log) {
96
+
97
+ console.groupCollapsed(#{title.join(', ').inspect});
98
+ console.log(#{response.join("\n").inspect});
99
+ console.log(#{call_stack_messages.join("\n").inspect});
100
+ console.groupEnd();
101
+
102
+ } else if (console.log) {
103
+
104
+ console.log(#{response.join("\n").inspect});
105
+ }
106
+ }
107
+ CODE
108
+ str << wrap_js_association(code)
98
109
  end
99
110
  str
100
111
  end
101
-
112
+
102
113
  def growl_notification
103
114
  if @@growl
104
115
  response = notification_response
@@ -113,77 +124,21 @@ module Bullet
113
124
  def log_notificatioin(path)
114
125
  if (@@bullet_logger || @@rails_logger) && (!unpreload_associations.empty? || !unused_preload_associations.empty?)
115
126
  Rails.logger.warn '' if @@rails_logger
116
- unused_preload_associations.each do |klazz, associations|
117
- log = ["Unused eager loadings: #{path}", klazz_associations_str(klazz, associations), " Remove from your finder: #{associations_str(associations)}"].join("\n")
118
- @@logger.info(log) if @@bullet_logger
119
- Rails.logger.warn(log) if @@rails_logger
127
+ unused_preload_messages(path).each do |message|
128
+ @@logger.info(message.join("\n")) if @@bullet_logger
129
+ Rails.logger.warn(message.join("\n")) if @@rails_logger
130
+ end
131
+ unpreload_messages(path).each do |message|
132
+ @@logger.info(message.join("\n")) if @@bullet_logger
133
+ Rails.logger.warn(message.join("\n")) if @@rails_logger
120
134
  end
121
- unpreload_associations.each do |klazz, associations|
122
- log = ["N+1 Query in #{path}", klazz_associations_str(klazz, associations), " Add to your finder: #{associations_str(associations)}"].join("\n")
123
- @@logger.info(log) if @@bullet_logger
124
- Rails.logger.warn(log) if @@rails_logger
125
- end
126
- callers.each do |c|
127
- log = ["N+1 Query method call stack", c.map{|line| " #{line}"}].flatten.join("\n")
128
- @@logger.info(log) if @@bullet_logger
129
- Rails.logger.warn(log) if @@rails_logger
135
+ call_stack_messages.each do |message|
136
+ @@logger.info(message.join("\n")) if @@bullet_logger
137
+ Rails.logger.warn(message.join("\n")) if @@rails_logger
130
138
  end
131
139
  @@logger_file.flush if @@bullet_logger
132
140
  end
133
141
  end
134
-
135
- def klazz_associations_str(klazz, associations)
136
- " #{klazz} => [#{associations.map(&:inspect).join(', ')}]"
137
- end
138
-
139
- def associations_str(associations)
140
- ":include => #{associations.map{|a| a.to_sym unless a.is_a? Hash}.inspect}"
141
- end
142
-
143
- def notification_response
144
- response = []
145
- if has_unused_preload_associations?
146
- response.push("Unused eager loadings detected:\n")
147
- response.push(*@@unused_preload_associations.to_a.collect{|klazz, associations| klazz_associations_str(klazz, associations)}.join("\n"))
148
- end
149
- if has_unpreload_associations?
150
- response.push("#{"\n" unless response.empty?}N+1 queries detected:\n")
151
- response.push(*@@unpreload_associations.to_a.collect{|klazz, associations| " #{klazz} => [#{associations.map(&:inspect).join(', ')}]"}.join("\n"))
152
- end
153
- response
154
- end
155
-
156
- def wrap_js_association(message)
157
- str = ''
158
- str << "<script type=\"text/javascript\">/*<![CDATA[*/"
159
- str << message
160
- str << "/*]]>*/</script>\n"
161
- end
162
-
163
- def has_klazz_association(klazz)
164
- !klazz_associations[klazz].nil? and klazz_associations.keys.include?(klazz)
165
- end
166
-
167
- def define_association(klazz, associations)
168
- # puts "define association, #{klazz} => #{associations.inspect}"
169
- add_klazz_associations(klazz, associations)
170
- end
171
-
172
- def call_association(object, associations)
173
- # puts "call association, #{object} => #{associations.inspect}"
174
- add_call_object_associations(object, associations)
175
- if unpreload_associations?(object, associations)
176
- add_unpreload_associations(object.class, associations)
177
- caller_in_project
178
- end
179
- end
180
-
181
- def unpreload_associations?(object, associations)
182
- klazz = object.class
183
- (!possible_objects[klazz].nil? and possible_objects[klazz].include?(object)) and
184
- (impossible_objects[klazz].nil? or !impossible_objects[klazz].include?(object)) and
185
- (object_associations[object].nil? or !object_associations[object].include?(associations))
186
- end
187
142
 
188
143
  def add_unpreload_associations(klazz, associations)
189
144
  # puts "add unpreload associations, #{klazz} => #{associations.inspect}"
@@ -191,7 +146,7 @@ module Bullet
191
146
  unpreload_associations[klazz] << associations
192
147
  unique(unpreload_associations[klazz])
193
148
  end
194
-
149
+
195
150
  def add_unused_preload_associations(klazz, associations)
196
151
  # puts "add unused preload associations, #{klazz} => #{associations.inspect}"
197
152
  unused_preload_associations[klazz] ||= []
@@ -206,6 +161,9 @@ module Bullet
206
161
  unique(object_associations[object])
207
162
  end
208
163
 
164
+ ###################################################
165
+ # interface for active record
166
+ ###################################################
209
167
  def add_call_object_associations(object, associations)
210
168
  # puts "add call object associations, #{object} => #{associations.inspect}"
211
169
  call_object_associations[object] ||= []
@@ -228,7 +186,7 @@ module Bullet
228
186
  impossible_objects[klazz] << object
229
187
  impossible_objects[klazz].uniq!
230
188
  end
231
-
189
+
232
190
  def add_klazz_associations(klazz, associations)
233
191
  # puts "define associations, #{klazz} => #{associations.inspect}"
234
192
  klazz_associations[klazz] ||= []
@@ -243,28 +201,127 @@ module Bullet
243
201
  eager_loadings[objects] << associations
244
202
  unique(eager_loadings[objects])
245
203
  end
204
+
205
+ def define_association(klazz, associations)
206
+ # puts "define association, #{klazz} => #{associations.inspect}"
207
+ add_klazz_associations(klazz, associations)
208
+ end
209
+
210
+ def call_association(object, associations)
211
+ # puts "call association, #{object} => #{associations.inspect}"
212
+ add_call_object_associations(object, associations)
213
+ if unpreload_associations?(object, associations)
214
+ add_unpreload_associations(object.class, associations)
215
+ caller_in_project
216
+ end
217
+ end
218
+
219
+ ############################################
220
+ # for rspec
221
+ ############################################
222
+ def check_unused_preload_associations
223
+ object_associations.each do |object, association|
224
+ related_objects = eager_loadings.select {|key, value| key.include?(object) and value == association}.collect(&:first).flatten
225
+ call_object_association = related_objects.collect { |related_object| call_object_associations[related_object] }.compact.flatten.uniq
226
+ diff_object_association = (association - call_object_association).reject {|a| a.is_a? Hash}
227
+ add_unused_preload_associations(object.class, diff_object_association) unless diff_object_association.empty?
228
+ end
229
+ end
230
+
231
+ def has_unused_preload_associations?
232
+ !unused_preload_associations.empty?
233
+ end
234
+
235
+ def has_unpreload_associations?
236
+ !unpreload_associations.empty?
237
+ end
238
+
239
+
240
+ private
241
+ def unpreload_associations?(object, associations)
242
+ klazz = object.class
243
+ (!possible_objects[klazz].nil? and possible_objects[klazz].include?(object)) and
244
+ (impossible_objects[klazz].nil? or !impossible_objects[klazz].include?(object)) and
245
+ (object_associations[object].nil? or !object_associations[object].include?(associations))
246
+ end
247
+
248
+ def notification_response
249
+ response = []
250
+ if has_unused_preload_associations?
251
+ response << unused_preload_messages.join("\n")
252
+ end
253
+ if has_unpreload_associations?
254
+ response << unpreload_messages.join("\n")
255
+ end
256
+ response
257
+ end
258
+
259
+ def unused_preload_messages(path = nil)
260
+ messages = []
261
+ unused_preload_associations.each do |klazz, associations|
262
+ messages << [
263
+ "Unused Eager Loading #{path ? "in #{path}" : 'detected'}",
264
+ klazz_associations_str(klazz, associations),
265
+ " Remove from your finder: #{associations_str(associations)}"
266
+ ]
267
+ end
268
+ messages
269
+ end
270
+
271
+ def unpreload_messages(path = nil)
272
+ messages = []
273
+ unpreload_associations.each do |klazz, associations|
274
+ messages << [
275
+ "N+1 Query #{path ? "in #{path}" : 'detected'}",
276
+ klazz_associations_str(klazz, associations),
277
+ " Add to your finder: #{associations_str(associations)}"
278
+ ]
279
+ end
280
+ messages
281
+ end
282
+
283
+ def klazz_associations_str(klazz, associations)
284
+ " #{klazz} => [#{associations.map(&:inspect).join(', ')}]"
285
+ end
286
+
287
+ def associations_str(associations)
288
+ ":include => #{associations.map{|a| a.to_sym unless a.is_a? Hash}.inspect}"
289
+ end
290
+
291
+ def wrap_js_association(message)
292
+ str = ''
293
+ str << "<script type=\"text/javascript\">/*<![CDATA[*/"
294
+ str << message
295
+ str << "/*]]>*/</script>\n"
296
+ end
297
+
298
+ def call_stack_messages
299
+ callers.inject([]) do |messages, c|
300
+ messages << ['N+1 Query method call stack', c.collect {|line| " #{line}"}].flatten
301
+ end
302
+ end
246
303
 
247
304
  def unique(array)
248
305
  array.flatten!
249
306
  array.uniq!
250
307
  end
251
-
308
+
252
309
  def unpreload_associations
253
310
  @@unpreload_associations ||= {}
254
311
  end
255
-
312
+
256
313
  def unused_preload_associations
257
314
  @@unused_preload_associations ||= {}
258
315
  end
259
-
316
+
260
317
  def object_associations
261
318
  @@object_associations ||= {}
262
319
  end
263
-
320
+
264
321
  def call_object_associations
265
322
  @@call_object_associations ||= {}
266
323
  end
267
-
324
+
268
325
  def possible_objects
269
326
  @@possible_objects ||= {}
270
327
  end
@@ -272,7 +329,7 @@ module Bullet
272
329
  def impossible_objects
273
330
  @@impossible_objects ||= {}
274
331
  end
275
-
332
+
276
333
  def klazz_associations
277
334
  @@klazz_associations ||= {}
278
335
  end
@@ -280,13 +337,13 @@ module Bullet
280
337
  def eager_loadings
281
338
  @@eager_loadings ||= {}
282
339
  end
283
-
340
+
284
341
  VENDOR_ROOT = File.join(RAILS_ROOT, 'vendor')
285
342
  def caller_in_project
286
343
  callers << caller.select {|c| c =~ /#{RAILS_ROOT}/}.reject {|c| c =~ /#{VENDOR_ROOT}/}
287
344
  callers.uniq!
288
345
  end
289
-
346
+
290
347
  def callers
291
348
  @@callers ||= []
292
349
  end
@@ -0,0 +1,29 @@
1
+ module Bullet
2
+ class Counter
3
+ class <<self
4
+ def start_request
5
+
6
+ end
7
+
8
+ def end_request
9
+ @@klazz_associations = nil
10
+ end
11
+
12
+ def need_counter_caches?
13
+ !klazz_associations.empty?
14
+ end
15
+
16
+ def add_counter_cache(object, associations)
17
+ klazz = object.class
18
+ klazz_associations[klazz] ||= []
19
+ klazz_associations[klazz] << associations
20
+ klazz_associations[klazz].flatten!
21
+ klazz_associations[klazz].uniq!
22
+ end
23
+
24
+ def klazz_associations
25
+ @@klazz_associations ||= {}
26
+ end
27
+ end
28
+ end
29
+ end
@@ -1,3 +1,5 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+
1
3
  ActiveRecord::Base.establish_connection(:adapter => 'sqlite3', :dbfile => ':memory:')
2
4
 
3
5
  describe Bullet::Association, 'has_many' do
@@ -0,0 +1,124 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+
3
+ ActiveRecord::Base.establish_connection(:adapter => 'sqlite3', :dbfile => ':memory:')
4
+
5
+ describe Bullet::Counter do
6
+ def setup_db
7
+ ActiveRecord::Schema.define(:version => 1) do
8
+ create_table :countries do |t|
9
+ t.string :name
10
+ end
11
+
12
+ create_table :cities do |t|
13
+ t.string :name
14
+ t.integer :country_id
15
+ end
16
+ end
17
+ end
18
+
19
+ def teardown_db
20
+ ActiveRecord::Base.connection.tables.each do |table|
21
+ ActiveRecord::Base.connection.drop_table(table)
22
+ end
23
+ end
24
+
25
+ class Country < ActiveRecord::Base
26
+ has_many :cities
27
+ end
28
+
29
+ class City < ActiveRecord::Base
30
+ belongs_to :country
31
+ end
32
+
33
+ before(:all) do
34
+ setup_db
35
+
36
+ country1 = Country.create(:name => 'first')
37
+ country2 = Country.create(:name => 'second')
38
+
39
+ country1.cities.create(:name => 'first')
40
+ country1.cities.create(:name => 'second')
41
+ country2.cities.create(:name => 'third')
42
+ country2.cities.create(:name => 'fourth')
43
+ end
44
+
45
+ after(:all) do
46
+ teardown_db
47
+ end
48
+
49
+ before(:each) do
50
+ Bullet::Counter.start_request
51
+ end
52
+
53
+ after(:each) do
54
+ Bullet::Counter.end_request
55
+ end
56
+
57
+ it "should need counter cache with count" do
58
+ Country.all.each do |country|
59
+ country.cities.size
60
+ end
61
+ Bullet::Counter.should be_need_counter_caches
62
+ end
63
+ end
64
+
65
+ describe Bullet::Counter do
66
+ def setup_db
67
+ ActiveRecord::Schema.define(:version => 1) do
68
+ create_table :people do |t|
69
+ t.string :name
70
+ t.integer :pets_count
71
+ end
72
+
73
+ create_table :pets do |t|
74
+ t.string :name
75
+ t.integer :person_id
76
+ end
77
+ end
78
+ end
79
+
80
+ def teardown_db
81
+ ActiveRecord::Base.connection.tables.each do |table|
82
+ ActiveRecord::Base.connection.drop_table(table)
83
+ end
84
+ end
85
+
86
+ class Person < ActiveRecord::Base
87
+ has_many :pets
88
+ end
89
+
90
+ class Pet < ActiveRecord::Base
91
+ belongs_to :person, :counter_cache => true
92
+ end
93
+
94
+ before(:all) do
95
+ setup_db
96
+
97
+ person1 = Person.create(:name => 'first')
98
+ person2 = Person.create(:name => 'second')
99
+
100
+ person1.pets.create(:name => 'first')
101
+ person1.pets.create(:name => 'second')
102
+ person2.pets.create(:name => 'third')
103
+ person2.pets.create(:name => 'fourth')
104
+ end
105
+
106
+ after(:all) do
107
+ teardown_db
108
+ end
109
+
110
+ before(:each) do
111
+ Bullet::Counter.start_request
112
+ end
113
+
114
+ after(:each) do
115
+ Bullet::Counter.end_request
116
+ end
117
+
118
+ it "should need counter cache with count" do
119
+ Person.all.each do |person|
120
+ person.pets.size
121
+ end
122
+ Bullet::Counter.should_not be_need_counter_caches
123
+ end
124
+ end
data/spec/spec_helper.rb CHANGED
@@ -7,6 +7,7 @@ RAILS_ROOT = File.expand_path(__FILE__).split('/')[0..-3].join('/') unless defin
7
7
  require File.expand_path(File.join(File.dirname(__FILE__), '../lib/bullet/logger'))
8
8
  require File.expand_path(File.join(File.dirname(__FILE__), '../lib/bullet/active_record'))
9
9
  require File.expand_path(File.join(File.dirname(__FILE__), '../lib/bullet/association'))
10
+ require File.expand_path(File.join(File.dirname(__FILE__), '../lib/bullet/counter'))
10
11
  require File.expand_path(File.join(File.dirname(__FILE__), '../lib/bullet'))
11
12
  require File.expand_path(File.join(File.dirname(__FILE__), '../lib/bulletware'))
12
13
  Bullet.enable = true
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: flyerhzm-bullet
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.0
4
+ version: 1.4.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Richard Huang
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-09-03 00:00:00 -07:00
12
+ date: 2009-09-09 00:00:00 -07:00
13
13
  default_executable:
14
14
  dependencies: []
15
15
 
@@ -30,10 +30,12 @@ files:
30
30
  - lib/bullet.rb
31
31
  - lib/bullet/active_record.rb
32
32
  - lib/bullet/association.rb
33
+ - lib/bullet/counter.rb
33
34
  - lib/bullet/logger.rb
34
35
  - lib/bulletware.rb
35
36
  - rails/init.rb
36
37
  - spec/bullet_association_spec.rb
38
+ - spec/bullet_counter_spec.rb
37
39
  - spec/spec.opts
38
40
  - spec/spec_helper.rb
39
41
  - tasks/bullet_tasks.rake
@@ -65,4 +67,5 @@ specification_version: 3
65
67
  summary: A plugin to kill N+1 queries and unused eager loading
66
68
  test_files:
67
69
  - spec/bullet_association_spec.rb
70
+ - spec/bullet_counter_spec.rb
68
71
  - spec/spec_helper.rb