bullet 4.13.0 → 4.14.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e90d569b3150f0988aeb2f614513e4603f231a92
4
- data.tar.gz: 8106c975d3aa193772e6146757c2f55144f8205e
3
+ metadata.gz: cb37955eb9271242e6c93d070639487d27c41cc4
4
+ data.tar.gz: 3dcfaee4517be454ae076b8707b479357aef4810
5
5
  SHA512:
6
- metadata.gz: d7fdb81048632cf1c99bf42680ce5c78ef8f605be770088d2d7f623f25663fb1a00e8f860775175791b54245f1a610430372d7402b35e29b4a636148052ef0e6
7
- data.tar.gz: 12518c2cafae4fa1db72215e3d6430c1781f82601176db91edf5b7246f52305a9991f37f522517e71af3d4435b5159589efbc25379694e38c76726cedd85ffc0
6
+ metadata.gz: aad803335d34af96636af55b2db42e93770c1d989485bad7bcd6a5ac6b78c1cd95d5c133913d2fb606dd9cfedec078785a83d175dac42ebd408595866b791679
7
+ data.tar.gz: e53e36ef7782a6e94079b128eaebecde19501ce26c0204dd35dbc7df53b81313d0f8fa22c0a445c1f10f5f163cf23afcaa29c998279963667ca7b7f34cdc7c66
data/.travis.yml CHANGED
@@ -2,6 +2,7 @@ language: ruby
2
2
  rvm:
3
3
  - 2.1.2
4
4
  gemfile:
5
+ - Gemfile.rails-4.2
5
6
  - Gemfile.rails-4.1
6
7
  - Gemfile.rails-4.0
7
8
  - Gemfile.rails-3.2
data/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # Next Release
2
2
 
3
+ ## 4.14.0 (10/03/2014)
4
+
5
+ * Support rails 4.2
6
+ * Polish notification output
7
+ * Fix warning: `*' interpreted as argument prefix
8
+
3
9
  ## 4.13.0 (07/19/2014)
4
10
 
5
11
  * Support include? call on ar associations
data/Gemfile.rails-4.0 CHANGED
@@ -2,7 +2,7 @@ source "https://rubygems.org"
2
2
 
3
3
  gemspec
4
4
 
5
- gem 'rails', '~> 4.0.8'
5
+ gem 'rails', '~> 4.0.9'
6
6
  gem 'sqlite3', platforms: [:ruby]
7
7
  gem 'activerecord-jdbcsqlite3-adapter', platforms: [:jruby]
8
8
  gem 'activerecord-import'
data/Gemfile.rails-4.1 CHANGED
@@ -2,7 +2,7 @@ source "https://rubygems.org"
2
2
 
3
3
  gemspec
4
4
 
5
- gem 'rails', '~> 4.1.4'
5
+ gem 'rails', '~> 4.1.6'
6
6
  gem 'sqlite3'
7
7
  gem 'activerecord-jdbcsqlite3-adapter', platforms: [:jruby]
8
8
  gem 'activerecord-import'
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.beta2'
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
@@ -12,7 +12,7 @@ Best practice is to use Bullet in development mode or custom mode (staging, prof
12
12
 
13
13
  Bullet gem now supports **activerecord** >= 3.0 and **mongoid** >= 2.4.1.
14
14
 
15
- If you use activercord 2.x, please use bullet <= 4.5.0
15
+ If you use activerecord 2.x, please use bullet <= 4.5.0
16
16
 
17
17
  ## External Introduction
18
18
 
@@ -25,9 +25,9 @@ module Bullet
25
25
  alias_method :origin_preloaders_on, :preloaders_on
26
26
 
27
27
  def preloaders_on(association, records, scope)
28
+ records.compact!
28
29
  if records.first.class.name !~ /^HABTM_/
29
30
  records.each do |record|
30
- next unless record
31
31
  Bullet::Detector::Association.add_object_associations(record, association)
32
32
  end
33
33
  Bullet::Detector::UnusedEagerLoading.add_eager_loadings(records, association)
@@ -0,0 +1,149 @@
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_/
121
+ Bullet::Detector::NPlusOneQuery.call_association(@owner, @reflection.name) unless @inversed
122
+ Bullet::Detector::NPlusOneQuery.add_possible_objects(result)
123
+ end
124
+ result
125
+ end
126
+ end
127
+
128
+ ::ActiveRecord::Associations::HasManyAssociation.class_eval do
129
+ alias_method :origin_many_empty?, :empty?
130
+ def empty?
131
+ Thread.current[:bullet_collection_empty] = true
132
+ result = origin_many_empty?
133
+ Thread.current[:bullet_collection_empty] = nil
134
+ Bullet::Detector::NPlusOneQuery.call_association(@owner, @reflection.name)
135
+ result
136
+ end
137
+
138
+ alias_method :origin_has_cached_counter?, :has_cached_counter?
139
+ def has_cached_counter?(reflection = reflection())
140
+ result = origin_has_cached_counter?(reflection)
141
+ if !result && !Thread.current[:bullet_collection_empty]
142
+ Bullet::Detector::CounterCache.add_counter_cache(owner, reflection.name)
143
+ end
144
+ result
145
+ end
146
+ end
147
+ end
148
+ end
149
+ end
@@ -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
@@ -47,7 +47,7 @@ module Bullet
47
47
  end
48
48
  end
49
49
 
50
- eager_loadings.add *to_add if to_add
50
+ eager_loadings.add(*to_add) if to_add
51
51
  to_merge.each { |k,val| eager_loadings.merge k, val }
52
52
  to_delete.each { |k| eager_loadings.delete k }
53
53
 
@@ -1,6 +1,6 @@
1
1
  class Object
2
2
  def bullet_key
3
- [self.class, self.primary_key_value].join(':')
3
+ "#{self.class}:#{self.primary_key_value}"
4
4
  end
5
5
 
6
6
  def primary_key_value
@@ -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("\n")
47
+ [whoami.presence, url, title, body].compact.join(" ")
52
48
  end
53
49
 
54
50
  def notification_data
@@ -7,10 +7,6 @@ module Bullet
7
7
  @callers = callers
8
8
  end
9
9
 
10
- def body_with_caller
11
- "#{body}\n#{call_stack_messages}"
12
- end
13
-
14
10
  def body
15
11
  "#{klazz_associations_str}\n Add to your finder: #{associations_str}"
16
12
  end
data/lib/bullet/rack.rb CHANGED
@@ -20,11 +20,11 @@ module Bullet
20
20
  headers['Content-Length'] = response_body.bytesize.to_s
21
21
  end
22
22
  end
23
- [status, headers, response_body ? [response_body] : response]
24
- ensure
25
23
  if Bullet.enable? && Bullet.notification?
26
24
  Bullet.perform_out_of_channel_notifications(env)
27
25
  end
26
+ [status, headers, response_body ? [response_body] : response]
27
+ ensure
28
28
  Bullet.end_request
29
29
  end
30
30
 
@@ -43,7 +43,7 @@ module Bullet
43
43
  end
44
44
 
45
45
  def add_footer_note(response_body)
46
- response_body << "<div #{footer_div_style}>" + Bullet.footer_info.uniq.join("<br>") + "</div>"
46
+ response_body << "<div #{footer_div_attributes}>" + Bullet.footer_info.uniq.join("<br>") + "</div>"
47
47
  end
48
48
 
49
49
  def file?(headers)
@@ -67,9 +67,9 @@ module Bullet
67
67
  end
68
68
 
69
69
  private
70
- def footer_div_style
70
+ def footer_div_attributes
71
71
  <<EOF
72
- style="position: fixed; bottom: 0pt; left: 0pt; cursor: pointer; border-style: solid; border-color: rgb(153, 153, 153);
72
+ data-is-bullet-footer style="position: fixed; bottom: 0pt; left: 0pt; cursor: pointer; border-style: solid; border-color: rgb(153, 153, 153);
73
73
  -moz-border-top-colors: none; -moz-border-right-colors: none; -moz-border-bottom-colors: none;
74
74
  -moz-border-left-colors: none; -moz-border-image: none; border-width: 2pt 2pt 0px 0px;
75
75
  padding: 5px; border-radius: 0pt 10pt 0pt 0px; background: none repeat scroll 0% 0% rgba(200, 200, 200, 0.8);
@@ -78,4 +78,3 @@ EOF
78
78
  end
79
79
  end
80
80
  end
81
-
@@ -1,4 +1,4 @@
1
1
  # encoding: utf-8
2
2
  module Bullet
3
- VERSION = "4.13.0"
3
+ VERSION = "4.14.0"
4
4
  end
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 = [env['HTTP_HOST'], env['REQUEST_URI']].compact.join
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
- expect(subject.body_with_caller).to eq("body")
60
- end
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,8 +5,8 @@ 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: :include => [:comments, :votes]\nN+1 Query method call stack\n caller1\n caller2") }
9
- it { expect([ subject.body_with_caller, subject.body_with_caller]).to eq([ " Post => [:comments, :votes]\n Add to your finder: :include => [:comments, :votes]\nN+1 Query method call stack\n caller1\n caller2", " Post => [:comments, :votes]\n Add to your finder: :include => [:comments, :votes]\nN+1 Query method call stack\n caller1\n caller2" ]) }
8
+ it { expect(subject.body_with_caller).to eq(" Post => [:comments, :votes]\n Add to your finder: :include => [: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: :include => [:comments, :votes]\nN+1 Query method call stack\n caller1\n caller2\n", " Post => [:comments, :votes]\n Add to your finder: :include => [:comments, :votes]\nN+1 Query method call stack\n caller1\n caller2\n" ]) }
10
10
  it { expect(subject.body).to eq(" Post => [:comments, :votes]\n Add to your finder: :include => [:comments, :votes]") }
11
11
  it { expect(subject.title).to eq("N+1 Query in path") }
12
12
  end
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
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.13.0
4
+ version: 4.14.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: 2014-07-19 00:00:00.000000000 Z
11
+ date: 2014-10-03 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