bullet 2.0.0.beta.2 → 2.0.0.beta.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. data/.rspec +1 -0
  2. data/Hacking.textile +100 -0
  3. data/README.textile +36 -5
  4. data/README_for_rails2.textile +17 -0
  5. data/Rakefile +33 -16
  6. data/VERSION +1 -1
  7. data/autotest/discover.rb +1 -0
  8. data/bullet.gemspec +32 -9
  9. data/lib/bullet.rb +69 -38
  10. data/lib/bullet/action_controller2.rb +4 -4
  11. data/lib/bullet/active_record2.rb +16 -16
  12. data/lib/bullet/active_record3.rb +16 -25
  13. data/lib/bullet/detector.rb +9 -0
  14. data/lib/bullet/detector/association.rb +135 -0
  15. data/lib/bullet/detector/base.rb +19 -0
  16. data/lib/bullet/detector/counter.rb +43 -0
  17. data/lib/bullet/detector/n_plus_one_query.rb +39 -0
  18. data/lib/bullet/detector/unused_eager_association.rb +39 -0
  19. data/lib/bullet/notification.rb +4 -79
  20. data/lib/bullet/notification/base.rb +59 -0
  21. data/lib/bullet/notification/counter_cache.rb +13 -0
  22. data/lib/bullet/notification/n_plus_one_query.rb +32 -0
  23. data/lib/bullet/notification/unused_eager_loading.rb +14 -0
  24. data/lib/bullet/notification_collector.rb +25 -0
  25. data/lib/bullet/presenter.rb +13 -0
  26. data/lib/bullet/presenter/base.rb +9 -0
  27. data/lib/bullet/presenter/bullet_logger.rb +28 -0
  28. data/lib/bullet/presenter/growl.rb +40 -0
  29. data/lib/bullet/presenter/javascript_alert.rb +15 -0
  30. data/lib/bullet/presenter/javascript_console.rb +28 -0
  31. data/lib/bullet/presenter/javascript_helpers.rb +13 -0
  32. data/lib/bullet/presenter/rails_logger.rb +15 -0
  33. data/lib/bullet/presenter/xmpp.rb +56 -0
  34. data/lib/bullet/rack.rb +42 -0
  35. data/lib/bullet/registry.rb +7 -0
  36. data/lib/bullet/registry/association.rb +16 -0
  37. data/lib/bullet/registry/base.rb +39 -0
  38. data/lib/bullet/registry/object.rb +15 -0
  39. data/spec/bullet/association_for_chris_spec.rb +6 -6
  40. data/spec/bullet/association_for_peschkaj_spec.rb +6 -6
  41. data/spec/bullet/association_spec.rb +118 -262
  42. data/spec/bullet/counter_spec.rb +10 -10
  43. data/spec/spec_helper.rb +51 -17
  44. metadata +32 -9
  45. data/lib/bullet/association.rb +0 -294
  46. data/lib/bullet/counter.rb +0 -101
  47. data/lib/bullet/logger.rb +0 -9
  48. data/lib/bulletware.rb +0 -42
  49. data/spec/spec.opts +0 -3
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --colour --format d
data/Hacking.textile ADDED
@@ -0,0 +1,100 @@
1
+ h1. Bullet Overview for Developers
2
+ This file aims to give developers a quick tour of the bullet internals, making
3
+ it (hopefully) easier to extend or enhance the Bullet gem.
4
+
5
+ h2. General Control Flow aka. 10000 Meter View
6
+ When Rails is initialized, Bullet will extend ActiveRecord (and if you're using
7
+ Rails 2.x ActiveController too) with the relevant modules and methods found
8
+ in lib/bullet/active_recordX.rb and lib/bullet/action_controller2.rb. If you're
9
+ running Rails 3, Bullet will integrate itself as a middleware into the Rack
10
+ stack, so ActionController does not need to be extended.
11
+
12
+ The ActiveRecord extensions will call methods in a given detector class, when
13
+ certain methods are called.
14
+
15
+ Detector classes contain all the logic to recognize
16
+ a noteworthy event. If such an event is detected, an instance of the
17
+ corresponding Notification class is created and stored in a Set instance in the
18
+ main Bullet module (the 'notification collector').
19
+
20
+ Notification instances contain the message that will be displayed, and will
21
+ use a Presenter class to display their message to the user.
22
+
23
+ Each Presenter knows how to present the message either "inline" (as in: the
24
+ message text will be inlined into the request response, such as javascript
25
+ alerts) or "out-of-channel" (completely independent of the request response,
26
+ such as growl or xmpp).
27
+
28
+ So the flow of a request goes like this:
29
+ 1. Bullet.start_request is called, which resets all the detectors and empties
30
+ the notification collector
31
+ 2. The request is handled by Rails, and the installed ActiveRecord extensions
32
+ trigger Detector callbacks
33
+ 3. Detectors once called, will determine whether something noteworthy happend.
34
+ If yes, then a Notification is created and stored in the notification collector.
35
+ 4. Rails finishes handling the request
36
+ 5. For each notification in the collector, Bullet will iterate over each
37
+ Presenter and will try to generate an inline message that will be appended to
38
+ the generated reponse body.
39
+ 6. The response is returned to the client.
40
+ 7. Bullet will try to generate an out-of-channel message for each notification.
41
+ 8. Bullet calls end_request for each detector.
42
+ 9. Goto 1.
43
+
44
+ h2. Adding Presenters
45
+ To add a presenter, you will need to:
46
+ * Add the class to the PRESENTERS constant in the main Bullet module
47
+ * Add an autoload directive to lib/bullet/presenter.rb
48
+ * Create your presenter class in the Bullet::Presenter namespace
49
+
50
+ Presenter classes will need the following class methods:
51
+ * .active? which returns a boolean to indicate if the presenter is active (so
52
+ * that presenters the user doesn't want can be skipped).
53
+
54
+ and at least one of:
55
+ * .out_of_channel( notification ) which will display the notification to the
56
+ user outside of the request response
57
+ or
58
+ * .inline( notification ) which will generate the notification presentation fit
59
+ to be appended to the generated HTML request response (if you want to inject
60
+ content on the result page, such as a javascript alert).
61
+
62
+ Have a look at lib/bullet/javascript_alert.rb as a trivial example for an
63
+ inline presenter and lib/bullet/rails_logger.rb to see how a minimal
64
+ out-of-channel presenter looks like.
65
+
66
+ h2. Adding Notification Types
67
+ If you want to add more kinds of things that Bullet can detect, a little more
68
+ work is needed than if you were just adding a Presenter, but the concepts are
69
+ similar.
70
+
71
+ * Add the class to the DETECTORS constant in the main Bullet module
72
+ * Add (if needed) Rails monkey patches to Bullet.enable
73
+ * Create your presenter class in the Bullet::Detector namespace
74
+ * Add an autoload directive to lib/bullet/detector.rb
75
+ * Create a corresponding notification class in the Bullet::Notification namespace
76
+ * Add an autoload directive to lib/bullet/notification.rb
77
+
78
+ As a rule of thumb, you can assume that each Detector will have its own
79
+ Notification class. If you follow the principle of Separation of Concerns I
80
+ can't really think of an example where one would deviate from this rule.
81
+
82
+ Since the detection of pathological associations is a bit hairy, I'd recommend
83
+ having a look at the counter cache detector and associated notification to get
84
+ a feel for what is needed to get off the ground.
85
+
86
+ h3. Detectors
87
+ The only things you'll need to consider when building your Detector class is
88
+ that it will need to supply the .start_request, .end_request and .clear class
89
+ methods.
90
+
91
+ Simple implementations are provided by Bullet::Detector::Base for start_request
92
+ and end_request, you will have to supply your own clear method.
93
+
94
+ h3. Notifications
95
+ For notifications you will want to supply a #title and #body instance method,
96
+ and check to see if the #initialize and #full_notice methods in the
97
+ Bullet::Notification::Base class fit your needs.
98
+
99
+ The interaction with the presenters encapsulated in the Base class, so you
100
+ won't have to worry about that.
data/README.textile CHANGED
@@ -17,6 +17,7 @@ You can install it as a gem:
17
17
  <pre><code>
18
18
  sudo gem install bullet --pre
19
19
  </code></pre>
20
+
20
21
  ****************************************************************************
21
22
 
22
23
  h2. Configuration
@@ -29,6 +30,10 @@ config.after_initialize do
29
30
  Bullet.bullet_logger = true
30
31
  Bullet.console = true
31
32
  Bullet.growl = true
33
+ Bullet.xmpp = { :account => 'bullets_account@jabber.org',
34
+ :password => 'bullets_password_for_jabber',
35
+ :receiver => 'your_account@jabber.org',
36
+ :show_online_status => true }
32
37
  Bullet.rails_logger = true
33
38
  Bullet.disable_browser_cache = true
34
39
  end
@@ -43,13 +48,27 @@ It is recommended to config growl notification as follows if your collaborators
43
48
  end
44
49
  </code></pre>
45
50
 
46
- The code above will enable all five of the Bullet notification systems:
51
+ and similarly for XMPP:
52
+ <pre><code>
53
+ begin
54
+ require 'xmpp4r'
55
+ Bullet.xmpp = { :account => 'bullets_account@jabber.org',
56
+ :password => 'bullets_password_for_jabber',
57
+ :receiver => 'your_account@jabber.org',
58
+ :show_online_status => true }
59
+ rescue MissingSourceFile
60
+ end
61
+ </code></pre>
62
+
63
+
64
+ The code above will enable all six of the Bullet notification systems:
47
65
  * <code>Bullet.enable</code>: enable Bullet plugin/gem, otherwise do nothing
48
66
  * <code>Bullet.alert</code>: pop up a JavaScript alert in the browser
49
67
  * <code>Bullet.bullet_logger</code>: log to the Bullet log file (Rails.root/log/bullet.log)
50
68
  * <code>Bullet.rails_logger</code>: add warnings directly to the Rails log
51
69
  * <code>Bullet.console</code>: log warnings to your browser's console.log (Safari/Webkit browsers or Firefox w/Firebug installed)
52
70
  * <code>Bullet.growl</code>: pop up Growl warnings if your system has Growl installed. Requires a little bit of configuration
71
+ * <code>Bullet.xmpp</code>: send XMPP/Jabber notifications to the receiver indicated. Note that the code will currently not handle the adding of contacts, so you will need to make both accounts indicated know each other manually before you will receive any notifications. If you restart the development server frequently, the 'coming online' sound for the bullet account may start to annoy - in this case set :show_online_status to false; you will still get notifications, but the bullet account won't announce it's online status anymore.
53
72
  * <code>Bullet.disable_browser_cache</code>: disable browser cache which usually causes unexpected problems
54
73
 
55
74
  ****************************************************************************
@@ -105,6 +124,17 @@ ruby-growl gem has an issue about md5 in ruby 1.9, if you use growl and ruby 1.9
105
124
 
106
125
  ****************************************************************************
107
126
 
127
+ h2. XMPP/Jabber Support
128
+
129
+ To get XMPP support up-and-running for Bullet, follow the steps below:
130
+ * Install the xmpp4r gem: <code>sudo gem install xmpp4r</code>
131
+ * Make both the bullet and the receipient account add each other as contacts.
132
+ This will require you to manually log into both accounts, add each other
133
+ as contact and confirm each others contact request.
134
+ * Boot up your application. Bullet will automatically send an XMPP notification when XMPP is turned on.
135
+
136
+ ****************************************************************************
137
+
108
138
  h2. Important
109
139
 
110
140
  If you find bullet does not work for you, *please disable your browser's cache*.
@@ -155,6 +185,7 @@ h2. Links
155
185
 
156
186
  h2. Contributors
157
187
 
188
+ sriedel did a lot of awesome refactors, added xmpp notification support, and added Hacking.textile about how to extend to bullet plugin.
158
189
  flipsasser added Growl, console.log and Rails.log support, very awesome. And he also improved README.
159
190
  rainux added group style console.log.
160
191
  2collegebums added some great specs to generate red bar.
@@ -203,7 +234,7 @@ post2.comments.create(:name => 'fourth')
203
234
  <pre><code>
204
235
  <% @posts.each do |post| %>
205
236
  <tr>
206
- <td><%=h post.name %></td>
237
+ <td><%= post.name %></td>
207
238
  <td><%= post.comments.collect(&:name) %></td>
208
239
  <td><%= link_to 'Show', post %></td>
209
240
  <td><%= link_to 'Edit', edit_post_path(post) %></td>
@@ -315,7 +346,7 @@ a N+1 query fixed. Cool!
315
346
  <pre><code>
316
347
  <% @posts.each do |post| %>
317
348
  <tr>
318
- <td><%=h post.name %></td>
349
+ <td><%= post.name %></td>
319
350
  <td><%= link_to 'Show', post %></td>
320
351
  <td><%= link_to 'Edit', edit_post_path(post) %></td>
321
352
  <td><%= link_to 'Destroy', post, :confirm => 'Are you sure?', :method => :delete %></td>
@@ -355,8 +386,8 @@ Remove from your finder: :include => [:comments]
355
386
  <pre><code>
356
387
  <% @posts.each do |post| %>
357
388
  <tr>
358
- <td><%=h post.name %></td>
359
- <td><%=h post.comments.size %></td>
389
+ <td><%= post.name %></td>
390
+ <td><%= post.comments.size %></td>
360
391
  <td><%= link_to 'Show', post %></td>
361
392
  <td><%= link_to 'Edit', edit_post_path(post) %></td>
362
393
  <td><%= link_to 'Destroy', post, :confirm => 'Are you sure?', :method => :delete %></td>
@@ -18,6 +18,7 @@ There is a large refactor from gem 1.4 to 1.5, so if you upgrade to 1.5 gem, ple
18
18
 
19
19
  h2. Contributors
20
20
 
21
+ sriedel did a lot of awesome refactors, added xmpp notification support, and added Hacking.textile about how to extend to bullet plugin.
21
22
  flipsasser added Growl, console.log and Rails.log support, very awesome. And he also improved README.
22
23
  rainux added group style console.log.
23
24
  2collegebums added some great specs to generate red bar.
@@ -52,6 +53,10 @@ config.after_initialize do
52
53
  Bullet.growl = true
53
54
  Bullet.rails_logger = true
54
55
  Bullet.disable_browser_cache = true
56
+ Bullet.xmpp = { :account => 'bullets_account@jabber.org',
57
+ :password => 'bullets_password_for_jabber',
58
+ :receiver => 'your_account@jabber.org',
59
+ :show_online_status => true }
55
60
  end
56
61
  </code></pre>
57
62
 
@@ -64,6 +69,18 @@ It is recommended to config growl notification as follows if your collaborators
64
69
  end
65
70
  </code></pre>
66
71
 
72
+ and similarly for XMPP:
73
+ <pre><code>
74
+ begin
75
+ require 'xmpp4r'
76
+ Bullet.xmpp = { :account => 'bullets_account@jabber.org',
77
+ :password => 'bullets_password_for_jabber',
78
+ :receiver => 'your_account@jabber.org',
79
+ :show_online_status => true }
80
+ rescue MissingSourceFile
81
+ end
82
+ </code></pre>
83
+
67
84
  The code above will enable all five of the Bullet notification systems:
68
85
  * <code>Bullet.enable</code>: enable Bullet plugin/gem, otherwise do nothing
69
86
  * <code>Bullet.alert</code>: pop up a JavaScript alert in the browser
data/Rakefile CHANGED
@@ -6,7 +6,7 @@ require 'jeweler'
6
6
  desc 'Default: run unit tests.'
7
7
  task :default => :spec
8
8
 
9
- desc 'Generate documentation for the sitemap plugin.'
9
+ desc 'Generate documentation for the bullet plugin.'
10
10
  Rake::RDocTask.new(:rdoc) do |rdoc|
11
11
  rdoc.rdoc_dir = 'rdoc'
12
12
  rdoc.title = 'Bullet'
@@ -15,20 +15,37 @@ Rake::RDocTask.new(:rdoc) do |rdoc|
15
15
  rdoc.rdoc_files.include('lib/**/*.rb')
16
16
  end
17
17
 
18
- # FIXME: 'rake spec' will break the test, just run 'ruby spec/association_spec.rb'
19
- #desc "Run all specs in spec directory"
20
- #Rspec::Core::RakeTask.new(:spec) do |t|
21
- #t.pattern = FileList['spec/**/*_spec.rb']
22
- #end
18
+ RSpec::Core::RakeTask.new(:spec)
23
19
 
24
- Jeweler::Tasks.new do |gemspec|
25
- gemspec.name = "bullet"
26
- gemspec.summary = "A plugin to kill N+1 queries and unused eager loading"
27
- gemspec.description = "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."
28
- gemspec.email = "flyerhzm@gmail.com"
29
- gemspec.homepage = "http://github.com/flyerhzm/bullet"
30
- gemspec.authors = ["Richard Huang"]
31
- gemspec.files.exclude '.gitignore'
32
- gemspec.files.exclude 'log/*'
20
+ desc "Run all examples using rcov"
21
+ RSpec::Core::RakeTask.new :rcov => :cleanup_rcov_files do |t|
22
+ t.rcov = true
23
+ t.rcov_opts = %[-Ilib -Ispec --exclude "gems/*,spec/spec_helper.rb"]
24
+ t.rcov_opts << %[--no-html --aggregate coverage.data]
25
+ end
26
+
27
+ task :cleanup_rcov_files do
28
+ rm_rf 'coverage.data'
29
+ end
30
+
31
+ task :clobber do
32
+ rm_rf 'pkg'
33
+ rm_rf 'tmp'
34
+ rm_rf 'coverage'
35
+ end
36
+
37
+ begin
38
+ Jeweler::Tasks.new do |gemspec|
39
+ gemspec.name = "bullet"
40
+ gemspec.summary = "A rails plugin to kill N+1 queries and unused eager loading"
41
+ gemspec.description = "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."
42
+ gemspec.email = "flyerhzm@gmail.com"
43
+ gemspec.homepage = "http://github.com/flyerhzm/bullet"
44
+ gemspec.authors = ["Richard Huang"]
45
+ gemspec.files.exclude '.gitignore'
46
+ gemspec.files.exclude 'log/*'
47
+ end
48
+ Jeweler::GemcutterTasks.new
49
+ rescue LoadError
50
+ puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
33
51
  end
34
- Jeweler::GemcutterTasks.new
data/VERSION CHANGED
@@ -1 +1 @@
1
- 2.0.0.beta.2
1
+ 2.0.0.beta.3
@@ -0,0 +1 @@
1
+ Autotest.add_discovery { "rspec2" }
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 = "2.0.0.beta.2"
8
+ s.version = "2.0.0.beta.3"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new("> 1.3.1") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Richard Huang"]
12
- s.date = %q{2010-03-07}
12
+ s.date = %q{2010-07-14}
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 = [
@@ -17,27 +17,50 @@ Gem::Specification.new do |s|
17
17
  "README_for_rails2.textile"
18
18
  ]
19
19
  s.files = [
20
- "MIT-LICENSE",
20
+ ".rspec",
21
+ "Hacking.textile",
22
+ "MIT-LICENSE",
21
23
  "README.textile",
22
24
  "README_for_rails2.textile",
23
25
  "Rakefile",
24
26
  "VERSION",
27
+ "autotest/discover.rb",
25
28
  "bullet.gemspec",
26
29
  "lib/bullet.rb",
27
30
  "lib/bullet/action_controller2.rb",
28
31
  "lib/bullet/active_record2.rb",
29
32
  "lib/bullet/active_record3.rb",
30
- "lib/bullet/association.rb",
31
- "lib/bullet/counter.rb",
32
- "lib/bullet/logger.rb",
33
+ "lib/bullet/detector.rb",
34
+ "lib/bullet/detector/association.rb",
35
+ "lib/bullet/detector/base.rb",
36
+ "lib/bullet/detector/counter.rb",
37
+ "lib/bullet/detector/n_plus_one_query.rb",
38
+ "lib/bullet/detector/unused_eager_association.rb",
33
39
  "lib/bullet/notification.rb",
34
- "lib/bulletware.rb",
40
+ "lib/bullet/notification/base.rb",
41
+ "lib/bullet/notification/counter_cache.rb",
42
+ "lib/bullet/notification/n_plus_one_query.rb",
43
+ "lib/bullet/notification/unused_eager_loading.rb",
44
+ "lib/bullet/notification_collector.rb",
45
+ "lib/bullet/presenter.rb",
46
+ "lib/bullet/presenter/base.rb",
47
+ "lib/bullet/presenter/bullet_logger.rb",
48
+ "lib/bullet/presenter/growl.rb",
49
+ "lib/bullet/presenter/javascript_alert.rb",
50
+ "lib/bullet/presenter/javascript_console.rb",
51
+ "lib/bullet/presenter/javascript_helpers.rb",
52
+ "lib/bullet/presenter/rails_logger.rb",
53
+ "lib/bullet/presenter/xmpp.rb",
54
+ "lib/bullet/rack.rb",
55
+ "lib/bullet/registry.rb",
56
+ "lib/bullet/registry/association.rb",
57
+ "lib/bullet/registry/base.rb",
58
+ "lib/bullet/registry/object.rb",
35
59
  "rails/init.rb",
36
60
  "spec/bullet/association_for_chris_spec.rb",
37
61
  "spec/bullet/association_for_peschkaj_spec.rb",
38
62
  "spec/bullet/association_spec.rb",
39
63
  "spec/bullet/counter_spec.rb",
40
- "spec/spec.opts",
41
64
  "spec/spec_helper.rb",
42
65
  "tasks/bullet_tasks.rake"
43
66
  ]
@@ -45,7 +68,7 @@ Gem::Specification.new do |s|
45
68
  s.rdoc_options = ["--charset=UTF-8"]
46
69
  s.require_paths = ["lib"]
47
70
  s.rubygems_version = %q{1.3.6}
48
- s.summary = %q{A plugin to kill N+1 queries and unused eager loading}
71
+ s.summary = %q{A rails plugin to kill N+1 queries and unused eager loading}
49
72
  s.test_files = [
50
73
  "spec/spec_helper.rb",
51
74
  "spec/bullet/counter_spec.rb",
data/lib/bullet.rb CHANGED
@@ -1,31 +1,52 @@
1
- require 'bulletware'
1
+ require 'set'
2
2
 
3
3
  module Bullet
4
+ class NotificationError < StandardError; end
5
+
4
6
  if Rails.version =~ /^3.0/
5
7
  autoload :ActiveRecord, 'bullet/active_record3'
6
8
  else
7
9
  autoload :ActiveRecord, 'bullet/active_record2'
8
10
  autoload :ActionController, 'bullet/action_controller2'
9
11
  end
10
- autoload :Association, 'bullet/association'
11
- autoload :Counter, 'bullet/counter'
12
+ autoload :Rack, 'bullet/rack'
12
13
  autoload :BulletLogger, 'bullet/logger'
13
14
  autoload :Notification, 'bullet/notification'
15
+ autoload :Presenter, 'bullet/presenter'
16
+ autoload :Detector, 'bullet/detector'
17
+ autoload :Registry, 'bullet/registry'
18
+ autoload :NotificationCollector, 'bullet/notification_collector'
19
+
20
+ if defined? Rails::Railtie
21
+ # compatible with rails 3.0.0.beta4
22
+ class BulletRailtie < Rails::Railtie
23
+ initializer "bullet.configure_rails_initialization" do |app|
24
+ app.middleware.use Bullet::Rack
25
+ end
26
+ end
27
+ end
14
28
 
15
29
  class <<self
16
- attr_accessor :enable, :alert, :console, :growl, :growl_password, :rails_logger, :bullet_logger, :logger, :logger_file, :disable_browser_cache
30
+ attr_accessor :enable, :alert, :console, :growl, :growl_password, :rails_logger, :bullet_logger, :disable_browser_cache, :xmpp
31
+ attr_reader :notification_collector
32
+
33
+ DETECTORS = [ Bullet::Detector::NPlusOneQuery,
34
+ Bullet::Detector::UnusedEagerAssociation,
35
+ Bullet::Detector::Counter ]
17
36
 
37
+ PRESENTERS = [ Bullet::Presenter::JavascriptAlert,
38
+ Bullet::Presenter::JavascriptConsole,
39
+ Bullet::Presenter::Growl,
40
+ Bullet::Presenter::Xmpp,
41
+ Bullet::Presenter::RailsLogger,
42
+ Bullet::Presenter::BulletLogger ]
43
+
18
44
  def enable=(enable)
19
45
  @enable = enable
20
46
  if enable?
21
47
  Bullet::ActiveRecord.enable
22
- if Rails.version =~ /^3.0/
23
- require 'action_controller/metal'
24
- ::ActionController::Metal.middleware_stack.use Bulletware
25
- elsif Rails.version =~/^2.3/
48
+ if Rails.version =~ /^2./
26
49
  Bullet::ActionController.enable
27
- require 'action_controller/dispatcher'
28
- ::ActionController::Dispatcher.middleware.use Bulletware
29
50
  end
30
51
  end
31
52
  end
@@ -35,53 +56,63 @@ module Bullet
35
56
  end
36
57
 
37
58
  def growl=(growl)
38
- if growl
39
- begin
40
- require 'ruby-growl'
41
- growl = Growl.new('localhost', 'ruby-growl', ['Bullet Notification'], nil, @growl_password)
42
- growl.notify('Bullet Notification', 'Bullet Notification', 'Bullet Growl notifications have been turned on')
43
- rescue MissingSourceFile
44
- raise NotificationError.new('You must install the ruby-growl gem to use Growl notifications: `sudo gem install ruby-growl`')
45
- end
46
- end
47
- @growl = growl
59
+ Bullet::Presenter::Growl.setup_connection( self.growl_password ) if growl
48
60
  end
49
61
 
50
- def bullet_logger=(bullet_logger)
51
- if @bullet_logger = bullet_logger
52
- @logger_file = File.open(Bullet::BulletLogger::LOG_FILE, 'a+')
53
- @logger = Bullet::BulletLogger.new(@logger_file)
54
- end
62
+ def xmpp=(xmpp)
63
+ Bullet::Presenter::Xmpp.setup_connection( xmpp ) if xmpp
55
64
  end
56
65
 
57
- BULLETS = [Bullet::Association, Bullet::Counter]
66
+ def bullet_logger=(bullet_logger)
67
+ Bullet::Presenter::BulletLogger.setup if bullet_logger
68
+ end
58
69
 
59
70
  def start_request
60
- BULLETS.each {|bullet| bullet.start_request}
71
+ @notification_collector ||= Bullet::NotificationCollector.new
72
+ @notification_collector.reset
73
+ DETECTORS.each {|bullet| bullet.start_request}
61
74
  end
62
75
 
63
76
  def end_request
64
- BULLETS.each {|bullet| bullet.end_request}
77
+ DETECTORS.each {|bullet| bullet.end_request}
65
78
  end
66
79
 
67
80
  def clear
68
- BULLETS.each {|bullet| bullet.clear}
81
+ DETECTORS.each {|bullet| bullet.clear}
69
82
  end
70
83
 
71
- def notification?
72
- BULLETS.any? {|bullet| bullet.notification?}
84
+ def active_presenters
85
+ PRESENTERS.select { |presenter| presenter.send :active? }
73
86
  end
74
87
 
75
- def javascript_notification
76
- BULLETS.collect {|bullet| bullet.javascript_notification if bullet.notification?}.join("\n")
88
+ def notification?
89
+ Bullet::Detector::UnusedEagerAssociation.check_unused_preload_associations
90
+ @notification_collector.notifications_present?
77
91
  end
78
92
 
79
- def growl_notification
80
- BULLETS.each {|bullet| bullet.growl_notification if bullet.notification?}
93
+ def gather_inline_notifications
94
+ responses = []
95
+ for_each_active_presenter_with_notification do |notification|
96
+ responses << notification.present_inline
97
+ end
98
+ responses.join( "\n" )
81
99
  end
82
100
 
83
- def log_notification(path)
84
- BULLETS.each {|bullet| bullet.log_notification(path) if bullet.notification?}
101
+ def perform_out_of_channel_notifications
102
+ for_each_active_presenter_with_notification do |notification|
103
+ notification.present_out_of_channel
104
+ end
85
105
  end
106
+
107
+ private
108
+ def for_each_active_presenter_with_notification
109
+ active_presenters.each do |presenter|
110
+ @notification_collector.collection.each do |notification|
111
+ notification.presenter = presenter
112
+ yield notification
113
+ end
114
+ end
115
+ end
86
116
  end
87
- end
117
+
118
+ end