bullet 4.13.1 → 4.14.3
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.
- checksums.yaml +4 -4
- data/.travis.yml +1 -0
- data/CHANGELOG.md +17 -2
- data/Gemfile.mongoid-2.4 +2 -2
- data/Gemfile.mongoid-2.5 +2 -2
- data/Gemfile.mongoid-2.6 +1 -1
- data/Gemfile.mongoid-2.7 +2 -2
- data/Gemfile.mongoid-2.8 +2 -2
- data/Gemfile.mongoid-3.0 +2 -2
- data/Gemfile.mongoid-3.1 +2 -2
- data/Gemfile.mongoid-4.0 +1 -1
- data/Gemfile.rails-3.0 +1 -3
- data/Gemfile.rails-3.1 +1 -1
- data/Gemfile.rails-3.2 +1 -1
- data/Gemfile.rails-4.0 +1 -1
- data/Gemfile.rails-4.1 +1 -1
- data/Gemfile.rails-4.2 +19 -0
- data/README.md +2 -1
- data/lib/bullet/active_record4.rb +4 -2
- data/lib/bullet/active_record41.rb +2 -2
- data/lib/bullet/active_record42.rb +152 -0
- data/lib/bullet/dependency.rb +6 -0
- data/lib/bullet/detector/unused_eager_loading.rb +1 -1
- data/lib/bullet/ext/object.rb +1 -1
- data/lib/bullet/notification/base.rb +7 -11
- data/lib/bullet/notification/n_plus_one_query.rb +0 -4
- data/lib/bullet/rack.rb +16 -7
- data/lib/bullet/version.rb +1 -1
- data/lib/bullet.rb +1 -1
- data/spec/bullet/notification/base_spec.rb +2 -27
- data/spec/bullet/notification/n_plus_one_query_spec.rb +3 -3
- data/spec/bullet/notification/unused_eager_loading_spec.rb +1 -1
- data/spec/bullet/rack_spec.rb +1 -1
- data/spec/integration/active_record4/association_spec.rb +26 -1
- data/spec/models/category.rb +4 -1
- data/spec/models/comment.rb +2 -0
- data/spec/models/post.rb +7 -2
- data/spec/models/reply.rb +3 -0
- data/spec/models/submission.rb +1 -1
- data/spec/spec_helper.rb +2 -2
- data/spec/support/sqlite_seed.rb +14 -6
- data/test.sh +1 -0
- data/update.sh +14 -0
- metadata +8 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: dbe02316f8b3e0b61718c940420f189423c3f5f0
|
|
4
|
+
data.tar.gz: 93db165a6618fb9c470081013e4b2f5fe002c602
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 6c9ec0b4e3c23e6de5f59f74cb9378f5db7c32a448a42d4304b2399c3762308bab649dffc7f86bd04aaf175946391df9658994a1a190fb2a64fb8ec5bd21dbb3
|
|
7
|
+
data.tar.gz: 47451dec206f2d05aaa11466d8f6c063bbb9e3e9c03929d7dc8867b11e77be6871ee6a58f1f2b52435db3bb6854e913228dc9b310bf7dd78f5b968de5f042932
|
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
|
@@ -1,8 +1,23 @@
|
|
|
1
1
|
# Next Release
|
|
2
2
|
|
|
3
|
-
## 4.
|
|
3
|
+
## 4.14.3
|
|
4
4
|
|
|
5
|
-
* Fix
|
|
5
|
+
* Fix false positive on create
|
|
6
|
+
|
|
7
|
+
## 4.14.2
|
|
8
|
+
|
|
9
|
+
* Hotfix nil object when add_impossible_object
|
|
10
|
+
|
|
11
|
+
## 4.14.1
|
|
12
|
+
|
|
13
|
+
* Fix has_one then has_many associations in rails 4.2
|
|
14
|
+
* Append js and dom to html body in proper position
|
|
15
|
+
|
|
16
|
+
## 4.14.0 (10/03/2014)
|
|
17
|
+
|
|
18
|
+
* Support rails 4.2
|
|
19
|
+
* Polish notification output
|
|
20
|
+
* Fix warning: `*' interpreted as argument prefix
|
|
6
21
|
|
|
7
22
|
## 4.13.0 (07/19/2014)
|
|
8
23
|
|
data/Gemfile.mongoid-2.4
CHANGED
|
@@ -2,10 +2,10 @@ source "https://rubygems.org"
|
|
|
2
2
|
|
|
3
3
|
gemspec
|
|
4
4
|
|
|
5
|
-
gem 'rails', '~> 3.2.
|
|
5
|
+
gem 'rails', '~> 3.2.0'
|
|
6
6
|
gem 'sqlite3', platforms: [:ruby]
|
|
7
7
|
gem 'activerecord-jdbcsqlite3-adapter', platforms: [:jruby]
|
|
8
|
-
gem 'mongoid', '~> 2.4.
|
|
8
|
+
gem 'mongoid', '~> 2.4.0'
|
|
9
9
|
|
|
10
10
|
gem "rspec"
|
|
11
11
|
gem "guard"
|
data/Gemfile.mongoid-2.5
CHANGED
|
@@ -2,10 +2,10 @@ source "https://rubygems.org"
|
|
|
2
2
|
|
|
3
3
|
gemspec
|
|
4
4
|
|
|
5
|
-
gem 'rails', '~> 3.2.
|
|
5
|
+
gem 'rails', '~> 3.2.0'
|
|
6
6
|
gem 'sqlite3', platforms: [:ruby]
|
|
7
7
|
gem 'activerecord-jdbcsqlite3-adapter', platforms: [:jruby]
|
|
8
|
-
gem 'mongoid', '~> 2.5.
|
|
8
|
+
gem 'mongoid', '~> 2.5.0'
|
|
9
9
|
|
|
10
10
|
gem "rspec"
|
|
11
11
|
gem "guard"
|
data/Gemfile.mongoid-2.6
CHANGED
data/Gemfile.mongoid-2.7
CHANGED
|
@@ -2,10 +2,10 @@ source "https://rubygems.org"
|
|
|
2
2
|
|
|
3
3
|
gemspec
|
|
4
4
|
|
|
5
|
-
gem 'rails', '~> 3.2.
|
|
5
|
+
gem 'rails', '~> 3.2.0'
|
|
6
6
|
gem 'sqlite3', platforms: [:ruby]
|
|
7
7
|
gem 'activerecord-jdbcsqlite3-adapter', platforms: [:jruby]
|
|
8
|
-
gem 'mongoid', '~> 2.7.
|
|
8
|
+
gem 'mongoid', '~> 2.7.0'
|
|
9
9
|
|
|
10
10
|
gem "rspec"
|
|
11
11
|
gem "guard"
|
data/Gemfile.mongoid-2.8
CHANGED
|
@@ -2,10 +2,10 @@ source "https://rubygems.org"
|
|
|
2
2
|
|
|
3
3
|
gemspec
|
|
4
4
|
|
|
5
|
-
gem 'rails', '~> 3.2'
|
|
5
|
+
gem 'rails', '~> 3.2.0'
|
|
6
6
|
gem 'sqlite3', platforms: [:ruby]
|
|
7
7
|
gem 'activerecord-jdbcsqlite3-adapter', platforms: [:jruby]
|
|
8
|
-
gem 'mongoid', '~> 2.8'
|
|
8
|
+
gem 'mongoid', '~> 2.8.0'
|
|
9
9
|
|
|
10
10
|
gem "rspec"
|
|
11
11
|
gem "guard"
|
data/Gemfile.mongoid-3.0
CHANGED
|
@@ -2,10 +2,10 @@ source "https://rubygems.org"
|
|
|
2
2
|
|
|
3
3
|
gemspec
|
|
4
4
|
|
|
5
|
-
gem 'rails', '~> 3.2.
|
|
5
|
+
gem 'rails', '~> 3.2.0'
|
|
6
6
|
gem 'sqlite3', platforms: [:ruby]
|
|
7
7
|
gem 'activerecord-jdbcsqlite3-adapter', platforms: [:jruby]
|
|
8
|
-
gem 'mongoid', '~> 3.0.
|
|
8
|
+
gem 'mongoid', '~> 3.0.0'
|
|
9
9
|
|
|
10
10
|
gem "rspec"
|
|
11
11
|
gem "guard"
|
data/Gemfile.mongoid-3.1
CHANGED
|
@@ -2,10 +2,10 @@ source "https://rubygems.org"
|
|
|
2
2
|
|
|
3
3
|
gemspec
|
|
4
4
|
|
|
5
|
-
gem 'rails', '~> 3.2.
|
|
5
|
+
gem 'rails', '~> 3.2.0'
|
|
6
6
|
gem 'sqlite3', platforms: [:ruby]
|
|
7
7
|
gem 'activerecord-jdbcsqlite3-adapter', platforms: [:jruby]
|
|
8
|
-
gem 'mongoid', '~> 3.1.
|
|
8
|
+
gem 'mongoid', '~> 3.1.0'
|
|
9
9
|
|
|
10
10
|
gem "rspec"
|
|
11
11
|
gem "guard"
|
data/Gemfile.mongoid-4.0
CHANGED
data/Gemfile.rails-3.0
CHANGED
|
@@ -2,14 +2,12 @@ source "https://rubygems.org"
|
|
|
2
2
|
|
|
3
3
|
gemspec
|
|
4
4
|
|
|
5
|
-
gem 'rails', '~> 3.0.
|
|
5
|
+
gem 'rails', '~> 3.0.0'
|
|
6
6
|
gem 'sqlite3', platforms: [:ruby]
|
|
7
7
|
gem 'activerecord-jdbcsqlite3-adapter', platforms: [:jruby]
|
|
8
8
|
gem 'activerecord-import'
|
|
9
9
|
|
|
10
10
|
gem "rspec"
|
|
11
|
-
gem "guard"
|
|
12
|
-
gem "guard-rspec"
|
|
13
11
|
|
|
14
12
|
gem 'coveralls', require: false
|
|
15
13
|
|
data/Gemfile.rails-3.1
CHANGED
data/Gemfile.rails-3.2
CHANGED
data/Gemfile.rails-4.0
CHANGED
data/Gemfile.rails-4.1
CHANGED
data/Gemfile.rails-4.2
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
source "https://rubygems.org"
|
|
2
|
+
|
|
3
|
+
gemspec
|
|
4
|
+
|
|
5
|
+
gem 'rails', '~> 4.2.0'
|
|
6
|
+
gem 'sqlite3'
|
|
7
|
+
gem 'activerecord-jdbcsqlite3-adapter', platforms: [:jruby]
|
|
8
|
+
gem 'activerecord-import'
|
|
9
|
+
|
|
10
|
+
gem "rspec"
|
|
11
|
+
gem "guard"
|
|
12
|
+
gem "guard-rspec"
|
|
13
|
+
|
|
14
|
+
gem 'coveralls', require: false
|
|
15
|
+
|
|
16
|
+
platforms :rbx do
|
|
17
|
+
gem 'rubysl', '~> 2.0'
|
|
18
|
+
gem 'rubinius-developer_tools'
|
|
19
|
+
end
|
data/README.md
CHANGED
|
@@ -67,6 +67,7 @@ The code above will enable all seven of the Bullet notification systems:
|
|
|
67
67
|
* `Bullet.alert`: pop up a JavaScript alert in the browser
|
|
68
68
|
* `Bullet.bullet_logger`: log to the Bullet log file (Rails.root/log/bullet.log)
|
|
69
69
|
* `Bullet.rails_logger`: add warnings directly to the Rails log
|
|
70
|
+
* `Bullet.bugsnag`: add notifications to bugsnag
|
|
70
71
|
* `Bullet.airbrake`: add notifications to airbrake
|
|
71
72
|
* `Bullet.console`: log warnings to your browser's console.log (Safari/Webkit browsers or Firefox w/Firebug installed)
|
|
72
73
|
* `Bullet.growl`: pop up Growl warnings if your system has Growl installed. Requires a little bit of configuration
|
|
@@ -429,4 +430,4 @@ Meanwhile, there's a line appended to `log/bullet.log`
|
|
|
429
430
|
Post => [:comments]
|
|
430
431
|
```
|
|
431
432
|
|
|
432
|
-
Copyright (c) 2009 -
|
|
433
|
+
Copyright (c) 2009 - 2015 Richard Huang (flyerhzm@gmail.com), released under the MIT license
|
|
@@ -104,8 +104,10 @@ module Bullet
|
|
|
104
104
|
alias_method :origin_reader, :reader
|
|
105
105
|
def reader(force_reload = false)
|
|
106
106
|
result = origin_reader(force_reload)
|
|
107
|
-
|
|
108
|
-
|
|
107
|
+
unless @inversed
|
|
108
|
+
Bullet::Detector::NPlusOneQuery.call_association(@owner, @reflection.name)
|
|
109
|
+
Bullet::Detector::NPlusOneQuery.add_possible_objects(result)
|
|
110
|
+
end
|
|
109
111
|
result
|
|
110
112
|
end
|
|
111
113
|
end
|
|
@@ -106,8 +106,8 @@ module Bullet
|
|
|
106
106
|
alias_method :origin_reader, :reader
|
|
107
107
|
def reader(force_reload = false)
|
|
108
108
|
result = origin_reader(force_reload)
|
|
109
|
-
if @owner.class.name !~ /^HABTM_/
|
|
110
|
-
Bullet::Detector::NPlusOneQuery.call_association(@owner, @reflection.name)
|
|
109
|
+
if @owner.class.name !~ /^HABTM_/ && !@inversed
|
|
110
|
+
Bullet::Detector::NPlusOneQuery.call_association(@owner, @reflection.name)
|
|
111
111
|
Bullet::Detector::NPlusOneQuery.add_possible_objects(result)
|
|
112
112
|
end
|
|
113
113
|
result
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
module Bullet
|
|
2
|
+
module ActiveRecord
|
|
3
|
+
def self.enable
|
|
4
|
+
require 'active_record'
|
|
5
|
+
::ActiveRecord::Relation.class_eval do
|
|
6
|
+
alias_method :origin_to_a, :to_a
|
|
7
|
+
# if select a collection of objects, then these objects have possible to cause N+1 query.
|
|
8
|
+
# if select only one object, then the only one object has impossible to cause N+1 query.
|
|
9
|
+
def to_a
|
|
10
|
+
records = origin_to_a
|
|
11
|
+
if records.first.class.name !~ /^HABTM_/
|
|
12
|
+
if records.size > 1
|
|
13
|
+
Bullet::Detector::NPlusOneQuery.add_possible_objects(records)
|
|
14
|
+
Bullet::Detector::CounterCache.add_possible_objects(records)
|
|
15
|
+
elsif records.size == 1
|
|
16
|
+
Bullet::Detector::NPlusOneQuery.add_impossible_object(records.first)
|
|
17
|
+
Bullet::Detector::CounterCache.add_impossible_object(records.first)
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
records
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
::ActiveRecord::Associations::Preloader.class_eval do
|
|
25
|
+
alias_method :origin_preloaders_on, :preloaders_on
|
|
26
|
+
|
|
27
|
+
def preloaders_on(association, records, scope)
|
|
28
|
+
records.compact!
|
|
29
|
+
if records.first.class.name !~ /^HABTM_/
|
|
30
|
+
records.each do |record|
|
|
31
|
+
Bullet::Detector::Association.add_object_associations(record, association)
|
|
32
|
+
end
|
|
33
|
+
Bullet::Detector::UnusedEagerLoading.add_eager_loadings(records, association)
|
|
34
|
+
end
|
|
35
|
+
origin_preloaders_on(association, records, scope)
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
::ActiveRecord::FinderMethods.class_eval do
|
|
40
|
+
# add includes in scope
|
|
41
|
+
alias_method :origin_find_with_associations, :find_with_associations
|
|
42
|
+
def find_with_associations
|
|
43
|
+
records = origin_find_with_associations
|
|
44
|
+
associations = (eager_load_values + includes_values).uniq
|
|
45
|
+
records.each do |record|
|
|
46
|
+
Bullet::Detector::Association.add_object_associations(record, associations)
|
|
47
|
+
end
|
|
48
|
+
Bullet::Detector::UnusedEagerLoading.add_eager_loadings(records, associations)
|
|
49
|
+
records
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
::ActiveRecord::Associations::JoinDependency.class_eval do
|
|
54
|
+
alias_method :origin_instantiate, :instantiate
|
|
55
|
+
alias_method :origin_construct_model, :construct_model
|
|
56
|
+
|
|
57
|
+
def instantiate(result_set, aliases)
|
|
58
|
+
@bullet_eager_loadings = {}
|
|
59
|
+
records = origin_instantiate(result_set, aliases)
|
|
60
|
+
|
|
61
|
+
@bullet_eager_loadings.each do |klazz, eager_loadings_hash|
|
|
62
|
+
objects = eager_loadings_hash.keys
|
|
63
|
+
Bullet::Detector::UnusedEagerLoading.add_eager_loadings(objects, eager_loadings_hash[objects.first].to_a)
|
|
64
|
+
end
|
|
65
|
+
records
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# call join associations
|
|
69
|
+
def construct_model(record, node, row, model_cache, id, aliases)
|
|
70
|
+
result = origin_construct_model(record, node, row, model_cache, id, aliases)
|
|
71
|
+
|
|
72
|
+
associations = node.reflection.name
|
|
73
|
+
Bullet::Detector::Association.add_object_associations(record, associations)
|
|
74
|
+
Bullet::Detector::NPlusOneQuery.call_association(record, associations)
|
|
75
|
+
@bullet_eager_loadings[record.class] ||= {}
|
|
76
|
+
@bullet_eager_loadings[record.class][record] ||= Set.new
|
|
77
|
+
@bullet_eager_loadings[record.class][record] << associations
|
|
78
|
+
|
|
79
|
+
result
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
::ActiveRecord::Associations::CollectionAssociation.class_eval do
|
|
84
|
+
# call one to many associations
|
|
85
|
+
alias_method :origin_load_target, :load_target
|
|
86
|
+
def load_target
|
|
87
|
+
Bullet::Detector::NPlusOneQuery.call_association(@owner, @reflection.name) unless @inversed
|
|
88
|
+
records = origin_load_target
|
|
89
|
+
|
|
90
|
+
if records.first.class.name !~ /^HABTM_/
|
|
91
|
+
if records.size > 1
|
|
92
|
+
Bullet::Detector::NPlusOneQuery.add_possible_objects(records)
|
|
93
|
+
Bullet::Detector::CounterCache.add_possible_objects(records)
|
|
94
|
+
elsif records.size == 1
|
|
95
|
+
Bullet::Detector::NPlusOneQuery.add_impossible_object(records.first)
|
|
96
|
+
Bullet::Detector::CounterCache.add_impossible_object(records.first)
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
records
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
alias_method :origin_empty?, :empty?
|
|
103
|
+
def empty?
|
|
104
|
+
Bullet::Detector::NPlusOneQuery.call_association(@owner, @reflection.name)
|
|
105
|
+
origin_empty?
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
alias_method :origin_include?, :include?
|
|
109
|
+
def include?(object)
|
|
110
|
+
Bullet::Detector::NPlusOneQuery.call_association(@owner, @reflection.name)
|
|
111
|
+
origin_include?(object)
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
::ActiveRecord::Associations::SingularAssociation.class_eval do
|
|
116
|
+
# call has_one and belongs_to associations
|
|
117
|
+
alias_method :origin_reader, :reader
|
|
118
|
+
def reader(force_reload = false)
|
|
119
|
+
result = origin_reader(force_reload)
|
|
120
|
+
if @owner.class.name !~ /^HABTM_/ && !@inversed
|
|
121
|
+
Bullet::Detector::NPlusOneQuery.call_association(@owner, @reflection.name)
|
|
122
|
+
Bullet::Detector::NPlusOneQuery.add_possible_objects(result)
|
|
123
|
+
end
|
|
124
|
+
if ::ActiveRecord::Reflection::HasOneReflection === @reflection && result
|
|
125
|
+
Bullet::Detector::NPlusOneQuery.add_impossible_object(result)
|
|
126
|
+
end
|
|
127
|
+
result
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
::ActiveRecord::Associations::HasManyAssociation.class_eval do
|
|
132
|
+
alias_method :origin_many_empty?, :empty?
|
|
133
|
+
def empty?
|
|
134
|
+
Thread.current[:bullet_collection_empty] = true
|
|
135
|
+
result = origin_many_empty?
|
|
136
|
+
Thread.current[:bullet_collection_empty] = nil
|
|
137
|
+
Bullet::Detector::NPlusOneQuery.call_association(@owner, @reflection.name)
|
|
138
|
+
result
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
alias_method :origin_has_cached_counter?, :has_cached_counter?
|
|
142
|
+
def has_cached_counter?(reflection = reflection())
|
|
143
|
+
result = origin_has_cached_counter?(reflection)
|
|
144
|
+
if !result && !Thread.current[:bullet_collection_empty]
|
|
145
|
+
Bullet::Detector::CounterCache.add_counter_cache(owner, reflection.name)
|
|
146
|
+
end
|
|
147
|
+
result
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
end
|
|
151
|
+
end
|
|
152
|
+
end
|
data/lib/bullet/dependency.rb
CHANGED
|
@@ -22,6 +22,8 @@ module Bullet
|
|
|
22
22
|
'active_record4'
|
|
23
23
|
elsif active_record41?
|
|
24
24
|
'active_record41'
|
|
25
|
+
elsif active_record42?
|
|
26
|
+
'active_record42'
|
|
25
27
|
end
|
|
26
28
|
end
|
|
27
29
|
end
|
|
@@ -66,6 +68,10 @@ module Bullet
|
|
|
66
68
|
active_record4? && ::ActiveRecord::VERSION::MINOR == 1
|
|
67
69
|
end
|
|
68
70
|
|
|
71
|
+
def active_record42?
|
|
72
|
+
active_record4? && ::ActiveRecord::VERSION::MINOR == 2
|
|
73
|
+
end
|
|
74
|
+
|
|
69
75
|
def mongoid2x?
|
|
70
76
|
mongoid? && ::Mongoid::VERSION =~ /\A2\.[4-8]/
|
|
71
77
|
end
|
data/lib/bullet/ext/object.rb
CHANGED
|
@@ -18,6 +18,10 @@ module Bullet
|
|
|
18
18
|
raise NoMethodError.new("no method body defined")
|
|
19
19
|
end
|
|
20
20
|
|
|
21
|
+
def call_stack_messages
|
|
22
|
+
""
|
|
23
|
+
end
|
|
24
|
+
|
|
21
25
|
def whoami
|
|
22
26
|
@user ||= ENV['USER'].presence || (`whoami`.chomp rescue "")
|
|
23
27
|
if @user.present?
|
|
@@ -28,15 +32,7 @@ module Bullet
|
|
|
28
32
|
end
|
|
29
33
|
|
|
30
34
|
def body_with_caller
|
|
31
|
-
body
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
def standard_notice
|
|
35
|
-
@standard_notifice ||= title + "\n" + body
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
def full_notice
|
|
39
|
-
[whoami.presence, url, title, body_with_caller].compact.join("\n")
|
|
35
|
+
"#{body}\n#{call_stack_messages}\n"
|
|
40
36
|
end
|
|
41
37
|
|
|
42
38
|
def notify_inline
|
|
@@ -48,7 +44,7 @@ module Bullet
|
|
|
48
44
|
end
|
|
49
45
|
|
|
50
46
|
def short_notice
|
|
51
|
-
[whoami.presence, url, title, body].compact.join("
|
|
47
|
+
[whoami.presence, url, title, body].compact.join(" ")
|
|
52
48
|
end
|
|
53
49
|
|
|
54
50
|
def notification_data
|
|
@@ -74,7 +70,7 @@ module Bullet
|
|
|
74
70
|
end
|
|
75
71
|
|
|
76
72
|
def associations_str
|
|
77
|
-
":
|
|
73
|
+
":includes => #{@associations.map{ |a| a.to_s.to_sym unless a.is_a? Hash }.inspect}"
|
|
78
74
|
end
|
|
79
75
|
end
|
|
80
76
|
end
|
data/lib/bullet/rack.rb
CHANGED
|
@@ -15,8 +15,9 @@ module Bullet
|
|
|
15
15
|
response_body = nil
|
|
16
16
|
if Bullet.notification?
|
|
17
17
|
if status == 200 && !response_body(response).frozen? && html_request?(headers, response)
|
|
18
|
-
response_body = response_body(response)
|
|
19
|
-
|
|
18
|
+
response_body = response_body(response)
|
|
19
|
+
append_to_html_body(response_body, footer_note) if Bullet.add_footer
|
|
20
|
+
append_to_html_body(response_body, Bullet.gather_inline_notifications)
|
|
20
21
|
headers['Content-Length'] = response_body.bytesize.to_s
|
|
21
22
|
end
|
|
22
23
|
end
|
|
@@ -42,8 +43,17 @@ module Bullet
|
|
|
42
43
|
end
|
|
43
44
|
end
|
|
44
45
|
|
|
45
|
-
def
|
|
46
|
-
response_body
|
|
46
|
+
def append_to_html_body(response_body, content)
|
|
47
|
+
if response_body.include?('</body>')
|
|
48
|
+
position = response_body.rindex('</body>')
|
|
49
|
+
response_body.insert(position, content)
|
|
50
|
+
else
|
|
51
|
+
response_body << content
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def footer_note
|
|
56
|
+
"<div #{footer_div_attributes}>" + Bullet.footer_info.uniq.join("<br>") + "</div>"
|
|
47
57
|
end
|
|
48
58
|
|
|
49
59
|
def file?(headers)
|
|
@@ -67,9 +77,9 @@ module Bullet
|
|
|
67
77
|
end
|
|
68
78
|
|
|
69
79
|
private
|
|
70
|
-
def
|
|
80
|
+
def footer_div_attributes
|
|
71
81
|
<<EOF
|
|
72
|
-
style="position: fixed; bottom: 0pt; left: 0pt; cursor: pointer; border-style: solid; border-color: rgb(153, 153, 153);
|
|
82
|
+
data-is-bullet-footer ondblclick="this.parentNode.removeChild(this);" style="position: fixed; bottom: 0pt; left: 0pt; cursor: pointer; border-style: solid; border-color: rgb(153, 153, 153);
|
|
73
83
|
-moz-border-top-colors: none; -moz-border-right-colors: none; -moz-border-bottom-colors: none;
|
|
74
84
|
-moz-border-left-colors: none; -moz-border-image: none; border-width: 2pt 2pt 0px 0px;
|
|
75
85
|
padding: 5px; border-radius: 0pt 10pt 0pt 0px; background: none repeat scroll 0% 0% rgba(200, 200, 200, 0.8);
|
|
@@ -78,4 +88,3 @@ EOF
|
|
|
78
88
|
end
|
|
79
89
|
end
|
|
80
90
|
end
|
|
81
|
-
|
data/lib/bullet/version.rb
CHANGED
data/lib/bullet.rb
CHANGED
|
@@ -153,7 +153,7 @@ module Bullet
|
|
|
153
153
|
|
|
154
154
|
def perform_out_of_channel_notifications(env = {})
|
|
155
155
|
for_each_active_notifier_with_notification do |notification|
|
|
156
|
-
notification.url =
|
|
156
|
+
notification.url = env['REQUEST_URI']
|
|
157
157
|
notification.notify_out_of_channel
|
|
158
158
|
end
|
|
159
159
|
end
|
|
@@ -56,33 +56,8 @@ module Bullet
|
|
|
56
56
|
context "#body_with_caller" do
|
|
57
57
|
it "should return body" do
|
|
58
58
|
allow(subject).to receive(:body).and_return("body")
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
end
|
|
62
|
-
|
|
63
|
-
context "#standard_notice" do
|
|
64
|
-
it "should return title + body" do
|
|
65
|
-
allow(subject).to receive(:title).and_return("title")
|
|
66
|
-
allow(subject).to receive(:body).and_return("body")
|
|
67
|
-
expect(subject.standard_notice).to eq("title\nbody")
|
|
68
|
-
end
|
|
69
|
-
end
|
|
70
|
-
|
|
71
|
-
context "#full_notice" do
|
|
72
|
-
it "should return whoami + url + title + body_with_caller" do
|
|
73
|
-
allow(subject).to receive(:whoami).and_return("whoami")
|
|
74
|
-
allow(subject).to receive(:url).and_return("url")
|
|
75
|
-
allow(subject).to receive(:title).and_return("title")
|
|
76
|
-
allow(subject).to receive(:body_with_caller).and_return("body_with_caller")
|
|
77
|
-
expect(subject.full_notice).to eq("whoami\nurl\ntitle\nbody_with_caller")
|
|
78
|
-
end
|
|
79
|
-
|
|
80
|
-
it "should return url + title + body_with_caller" do
|
|
81
|
-
allow(subject).to receive(:whoami).and_return("")
|
|
82
|
-
allow(subject).to receive(:url).and_return("url")
|
|
83
|
-
allow(subject).to receive(:title).and_return("title")
|
|
84
|
-
allow(subject).to receive(:body_with_caller).and_return("body_with_caller")
|
|
85
|
-
expect(subject.full_notice).to eq("url\ntitle\nbody_with_caller")
|
|
59
|
+
allow(subject).to receive(:call_stack_messages).and_return("call_stack_messages")
|
|
60
|
+
expect(subject.body_with_caller).to eq("body\ncall_stack_messages\n")
|
|
86
61
|
end
|
|
87
62
|
end
|
|
88
63
|
|
|
@@ -5,9 +5,9 @@ module Bullet
|
|
|
5
5
|
describe NPlusOneQuery do
|
|
6
6
|
subject { NPlusOneQuery.new([["caller1", "caller2"]], Post, [:comments, :votes], "path") }
|
|
7
7
|
|
|
8
|
-
it { expect(subject.body_with_caller).to eq(" Post => [:comments, :votes]\n Add to your finder: :
|
|
9
|
-
it { expect([
|
|
10
|
-
it { expect(subject.body).to eq(" Post => [:comments, :votes]\n Add to your finder: :
|
|
8
|
+
it { expect(subject.body_with_caller).to eq(" Post => [:comments, :votes]\n Add to your finder: :includes => [:comments, :votes]\nN+1 Query method call 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]\nN+1 Query method call stack\n caller1\n caller2\n", " Post => [:comments, :votes]\n Add to your finder: :includes => [:comments, :votes]\nN+1 Query method call 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
11
|
it { expect(subject.title).to eq("N+1 Query in path") }
|
|
12
12
|
end
|
|
13
13
|
end
|
|
@@ -5,7 +5,7 @@ module Bullet
|
|
|
5
5
|
describe UnusedEagerLoading do
|
|
6
6
|
subject { UnusedEagerLoading.new(Post, [:comments, :votes], "path") }
|
|
7
7
|
|
|
8
|
-
it { expect(subject.body).to eq(" Post => [:comments, :votes]\n Remove from your finder: :
|
|
8
|
+
it { expect(subject.body).to eq(" Post => [:comments, :votes]\n Remove from your finder: :includes => [:comments, :votes]") }
|
|
9
9
|
it { expect(subject.title).to eq("Unused Eager Loading in path") }
|
|
10
10
|
end
|
|
11
11
|
end
|
data/spec/bullet/rack_spec.rb
CHANGED
|
@@ -70,7 +70,7 @@ module Bullet
|
|
|
70
70
|
expect(Bullet).to receive(:perform_out_of_channel_notifications)
|
|
71
71
|
status, headers, response = middleware.call([200, {"Content-Type" => "text/html"}])
|
|
72
72
|
expect(headers["Content-Length"]).to eq("56")
|
|
73
|
-
expect(response).to eq(["<html><head></head><body></body></html
|
|
73
|
+
expect(response).to eq(["<html><head></head><body><bullet></bullet></body></html>"])
|
|
74
74
|
end
|
|
75
75
|
|
|
76
76
|
it "should set the right Content-Length if response body contains accents" do
|
|
@@ -219,6 +219,20 @@ if !mongoid? && active_record4?
|
|
|
219
219
|
|
|
220
220
|
expect(Bullet::Detector::Association).to be_completely_preloading_associations
|
|
221
221
|
end
|
|
222
|
+
|
|
223
|
+
it "should not detect unused preload with category => posts" do
|
|
224
|
+
category = Category.first
|
|
225
|
+
category.draft_post.destroy!
|
|
226
|
+
post = category.draft_post
|
|
227
|
+
post.update_attributes!(link: true)
|
|
228
|
+
Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
|
|
229
|
+
expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
|
|
230
|
+
|
|
231
|
+
expect(Bullet::Detector::Association).to be_completely_preloading_associations
|
|
232
|
+
|
|
233
|
+
Support::SqliteSeed.setup_db
|
|
234
|
+
Support::SqliteSeed.seed_db
|
|
235
|
+
end
|
|
222
236
|
end
|
|
223
237
|
|
|
224
238
|
context "category => posts => writer" do
|
|
@@ -313,7 +327,7 @@ if !mongoid? && active_record4?
|
|
|
313
327
|
expect(Bullet::Detector::Association).to be_completely_preloading_associations
|
|
314
328
|
end
|
|
315
329
|
|
|
316
|
-
it "should detect unused preload with
|
|
330
|
+
it "should detect unused preload with comment => post" do
|
|
317
331
|
Comment.includes(:post).map(&:name)
|
|
318
332
|
Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
|
|
319
333
|
expect(Bullet::Detector::Association).to be_unused_preload_associations_for(Comment, :post)
|
|
@@ -515,6 +529,17 @@ if !mongoid? && active_record4?
|
|
|
515
529
|
end
|
|
516
530
|
end
|
|
517
531
|
|
|
532
|
+
describe Bullet::Detector::Association, "has_one => has_many" do
|
|
533
|
+
it "should not detect preload association" do
|
|
534
|
+
user = User.first
|
|
535
|
+
user.submission.replies.map(&:name)
|
|
536
|
+
Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
|
|
537
|
+
expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
|
|
538
|
+
|
|
539
|
+
expect(Bullet::Detector::Association).to be_completely_preloading_associations
|
|
540
|
+
end
|
|
541
|
+
end
|
|
542
|
+
|
|
518
543
|
describe Bullet::Detector::Association, "call one association that in possible objects" do
|
|
519
544
|
it "should not detect preload association" do
|
|
520
545
|
Post.all
|
data/spec/models/category.rb
CHANGED
data/spec/models/comment.rb
CHANGED
data/spec/models/post.rb
CHANGED
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
class Post < ActiveRecord::Base
|
|
2
|
-
extend Bullet::Dependency
|
|
3
|
-
|
|
4
2
|
belongs_to :category, inverse_of: :posts
|
|
5
3
|
belongs_to :writer
|
|
6
4
|
has_many :comments, inverse_of: :post
|
|
7
5
|
|
|
6
|
+
validates :category, presence: true
|
|
7
|
+
|
|
8
8
|
scope :preload_comments, -> { includes(:comments) }
|
|
9
9
|
scope :in_category_name, ->(name) { where(['categories.name = ?', name]).includes(:category) }
|
|
10
|
+
scope :draft, -> { where(active: false) }
|
|
11
|
+
|
|
12
|
+
def link=(*)
|
|
13
|
+
comments.new
|
|
14
|
+
end
|
|
10
15
|
end
|
data/spec/models/submission.rb
CHANGED
data/spec/spec_helper.rb
CHANGED
data/spec/support/sqlite_seed.rb
CHANGED
|
@@ -14,7 +14,7 @@ module Support
|
|
|
14
14
|
category2 = Category.create(:name => 'second')
|
|
15
15
|
|
|
16
16
|
post1 = category1.posts.create(:name => 'first', :writer => writer1)
|
|
17
|
-
post1a = category1.posts.create(:name => 'like first', :writer => writer2)
|
|
17
|
+
post1a = category1.posts.create(:name => 'like first', :writer => writer2, active: false)
|
|
18
18
|
post2 = category2.posts.create(:name => 'second', :writer => writer2)
|
|
19
19
|
|
|
20
20
|
comment1 = post1.comments.create(:name => 'first', :author => writer1)
|
|
@@ -82,10 +82,13 @@ module Support
|
|
|
82
82
|
user1 = User.create(:name => 'user1', :category => category1)
|
|
83
83
|
user2 = User.create(:name => 'user2', :category => category1)
|
|
84
84
|
|
|
85
|
-
submission1 =
|
|
86
|
-
submission2 =
|
|
87
|
-
|
|
88
|
-
|
|
85
|
+
submission1 = user1.create_submission(:name => "submission1")
|
|
86
|
+
submission2 = user2.create_submission(:name => "submission2")
|
|
87
|
+
|
|
88
|
+
submission1.replies.create(:name => 'reply1')
|
|
89
|
+
submission1.replies.create(:name => 'reply2')
|
|
90
|
+
submission2.replies.create(:name => 'reply3')
|
|
91
|
+
submission2.replies.create(:name => 'reply4')
|
|
89
92
|
end
|
|
90
93
|
|
|
91
94
|
def setup_db
|
|
@@ -191,6 +194,7 @@ module Support
|
|
|
191
194
|
t.column :name, :string
|
|
192
195
|
t.column :category_id, :integer
|
|
193
196
|
t.column :writer_id, :integer
|
|
197
|
+
t.column :active, :boolean, :default => true
|
|
194
198
|
end
|
|
195
199
|
|
|
196
200
|
create_table :relationships do |t|
|
|
@@ -211,9 +215,13 @@ module Support
|
|
|
211
215
|
t.column :name, :string
|
|
212
216
|
end
|
|
213
217
|
|
|
218
|
+
create_table :replies do |t|
|
|
219
|
+
t.column :name, :string
|
|
220
|
+
t.column :submission_id, :integer
|
|
221
|
+
end
|
|
222
|
+
|
|
214
223
|
create_table :submissions do |t|
|
|
215
224
|
t.column :name, :string
|
|
216
|
-
t.column :category_id, :integer
|
|
217
225
|
t.column :user_id, :integer
|
|
218
226
|
end
|
|
219
227
|
|
data/test.sh
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
#bundle update rails && bundle exec rspec spec
|
|
2
2
|
#BUNDLE_GEMFILE=Gemfile.mongoid bundle update mongoid && BUNDLE_GEMFILE=Gemfile.mongoid bundle exec rspec spec
|
|
3
|
+
BUNDLE_GEMFILE=Gemfile.rails-4.2 bundle && BUNDLE_GEMFILE=Gemfile.rails-4.2 bundle exec rspec spec
|
|
3
4
|
BUNDLE_GEMFILE=Gemfile.rails-4.1 bundle && BUNDLE_GEMFILE=Gemfile.rails-4.1 bundle exec rspec spec
|
|
4
5
|
BUNDLE_GEMFILE=Gemfile.rails-4.0 bundle && BUNDLE_GEMFILE=Gemfile.rails-4.0 bundle exec rspec spec
|
|
5
6
|
BUNDLE_GEMFILE=Gemfile.rails-3.2 bundle && BUNDLE_GEMFILE=Gemfile.rails-3.2 bundle exec rspec spec
|
data/update.sh
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
BUNDLE_GEMFILE=Gemfile.rails-4.2 bundle update
|
|
2
|
+
BUNDLE_GEMFILE=Gemfile.rails-4.1 bundle update
|
|
3
|
+
BUNDLE_GEMFILE=Gemfile.rails-4.0 bundle update
|
|
4
|
+
BUNDLE_GEMFILE=Gemfile.rails-3.2 bundle update
|
|
5
|
+
BUNDLE_GEMFILE=Gemfile.rails-3.1 bundle update
|
|
6
|
+
BUNDLE_GEMFILE=Gemfile.rails-3.0 bundle update
|
|
7
|
+
BUNDLE_GEMFILE=Gemfile.mongoid-4.0 bundle update
|
|
8
|
+
BUNDLE_GEMFILE=Gemfile.mongoid-3.1 bundle update
|
|
9
|
+
BUNDLE_GEMFILE=Gemfile.mongoid-3.0 bundle update
|
|
10
|
+
BUNDLE_GEMFILE=Gemfile.mongoid-2.8 bundle update
|
|
11
|
+
BUNDLE_GEMFILE=Gemfile.mongoid-2.7 bundle update
|
|
12
|
+
BUNDLE_GEMFILE=Gemfile.mongoid-2.6 bundle update
|
|
13
|
+
BUNDLE_GEMFILE=Gemfile.mongoid-2.5 bundle update
|
|
14
|
+
BUNDLE_GEMFILE=Gemfile.mongoid-2.4 bundle update
|
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: 4.
|
|
4
|
+
version: 4.14.3
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Richard Huang
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2015-02-01 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: activesupport
|
|
@@ -64,6 +64,7 @@ files:
|
|
|
64
64
|
- Gemfile.rails-3.2
|
|
65
65
|
- Gemfile.rails-4.0
|
|
66
66
|
- Gemfile.rails-4.1
|
|
67
|
+
- Gemfile.rails-4.2
|
|
67
68
|
- Guardfile
|
|
68
69
|
- Hacking.md
|
|
69
70
|
- MIT-LICENSE
|
|
@@ -75,6 +76,7 @@ files:
|
|
|
75
76
|
- lib/bullet/active_record3x.rb
|
|
76
77
|
- lib/bullet/active_record4.rb
|
|
77
78
|
- lib/bullet/active_record41.rb
|
|
79
|
+
- lib/bullet/active_record42.rb
|
|
78
80
|
- lib/bullet/dependency.rb
|
|
79
81
|
- lib/bullet/detector.rb
|
|
80
82
|
- lib/bullet/detector/association.rb
|
|
@@ -148,6 +150,7 @@ files:
|
|
|
148
150
|
- spec/models/pet.rb
|
|
149
151
|
- spec/models/post.rb
|
|
150
152
|
- spec/models/relationship.rb
|
|
153
|
+
- spec/models/reply.rb
|
|
151
154
|
- spec/models/student.rb
|
|
152
155
|
- spec/models/submission.rb
|
|
153
156
|
- spec/models/teacher.rb
|
|
@@ -160,6 +163,7 @@ files:
|
|
|
160
163
|
- spec/support/sqlite_seed.rb
|
|
161
164
|
- tasks/bullet_tasks.rake
|
|
162
165
|
- test.sh
|
|
166
|
+
- update.sh
|
|
163
167
|
homepage: http://github.com/flyerhzm/bullet
|
|
164
168
|
licenses:
|
|
165
169
|
- MIT
|
|
@@ -180,7 +184,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
180
184
|
version: 1.3.6
|
|
181
185
|
requirements: []
|
|
182
186
|
rubyforge_project:
|
|
183
|
-
rubygems_version: 2.
|
|
187
|
+
rubygems_version: 2.4.5
|
|
184
188
|
signing_key:
|
|
185
189
|
specification_version: 4
|
|
186
190
|
summary: help to kill N+1 queries and unused eager loading.
|
|
@@ -232,6 +236,7 @@ test_files:
|
|
|
232
236
|
- spec/models/pet.rb
|
|
233
237
|
- spec/models/post.rb
|
|
234
238
|
- spec/models/relationship.rb
|
|
239
|
+
- spec/models/reply.rb
|
|
235
240
|
- spec/models/student.rb
|
|
236
241
|
- spec/models/submission.rb
|
|
237
242
|
- spec/models/teacher.rb
|