rspec-sqlimit 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 475c6503c3977cff0ade02d623b23dfe2465b94f
4
- data.tar.gz: 2d9f1030c97a6eb4d156d6a25ee38e46c44456ee
3
+ metadata.gz: fb112af9504128b90adde574c3ec62eb7853a35e
4
+ data.tar.gz: 5a7a2d7ed16fc1224168435263f27d59e943530d
5
5
  SHA512:
6
- metadata.gz: c687ef9cb2d62c639cd924c90e6ee61417ddfe041e28f13c142b45e9ea35305d8d0f125c125c9d5cd6354dc937a0f9b8d3ab85414ddaaf79c1b3d0ff7a934b0b
7
- data.tar.gz: 57a9ac1ed2e7a67f37def16516becfc1b38dfd403eccfe389f2e0b32498e446906f8d1ca8767823f8e3950892ed29a7385adc4d01c3251ecfda522ebe5772fb3
6
+ metadata.gz: 943305eafecad8557ed1ef7baaca8eb02ae9c2f05da61f538c6412fb49a568ac5df7e686c8455b47fc20d919ade80704d071e328197c51d54b96e6699d7b8b24
7
+ data.tar.gz: 8cede3b49a91a9ce2ab17869e94fa4a674c157ecd7043f73a95a0d25552fb51e63b4648a7cc2c2c1320642233f585234137a087ca71a2954f6c7c3b34a50af58
data/.gitignore CHANGED
@@ -7,3 +7,4 @@
7
7
  /pkg/
8
8
  /spec/reports/
9
9
  /tmp/
10
+ /spec/dummy/db/*.sqlite3
@@ -3,7 +3,7 @@ sudo: false
3
3
  language: ruby
4
4
  cache: bundler
5
5
  script:
6
- - bundle exec rspec
6
+ - bundle exec rake
7
7
  rvm:
8
8
  - 2.3.0
9
9
  - ruby-head
@@ -0,0 +1,18 @@
1
+ # Change Log
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](http://keepachangelog.com/)
6
+ and this project adheres to [Semantic Versioning](http://semver.org/).
7
+
8
+ ## [0.0.2] - [2017-05-17]
9
+
10
+ ### Added
11
+ - All variables of SQL queries are bound to error messages (@Dobrodushny)
12
+
13
+ ## [0.0.1] - [2017-02-12]
14
+ This is a first public release (@nepalez)
15
+
16
+ [Unreleased]: https://github.com/tram-rb/tram-policy
17
+ [0.0.1]: https://github.com/nepalez/rspec-sqlimit/releases/tag/v0.0.1
18
+ [0.0.2]: https://github.com/nepalez/rspec-sqlimit/compare/v0.0.1...v0.0.2
data/README.md CHANGED
@@ -4,6 +4,8 @@ RSpec matcher to control number of SQL queries executed by a block of code.
4
4
 
5
5
  It wraps [the answer at Stack Overflow][stack-answer] by [Ryan Bigg][ryan-bigg], which based on Active Support [Notification][notification] and [Instrumentation][instrumentation] mechanisms.
6
6
 
7
+ For motivation and details see my [blog post "Fighting the Hydra of N+1 queries" in the Martian Chronicles][hydra].
8
+
7
9
  [![Gem Version][gem-badger]][gem]
8
10
  [![Build Status][travis-badger]][travis]
9
11
  [![Dependency Status][gemnasium-badger]][gemnasium]
@@ -66,31 +68,7 @@ require "rspec-sqlimit"
66
68
 
67
69
  RSpec.describe "N+1 safety" do
68
70
  it "doesn't send unnecessary requests to db" do
69
- expect { User.create }.not_to exceed_query_limit(1).with(/^INSERT/)
70
- end
71
- end
72
- ```
73
-
74
- ```
75
- Failure/Error: expect { User.create }.not_to exceed_query_limit(0).with(/INSERT/)
76
-
77
- Expected to run maximum 0 queries that match (?-mix:INSERT)
78
- The following 1 queries were invoked among others (see mark ->):
79
- 1) begin transaction (0.072 ms)
80
- -> 2) INSERT INTO "users" DEFAULT VALUES (0.368 ms)
81
- 3) commit transaction (147.559 ms)
82
- ```
83
-
84
- ## Further Development
85
-
86
- For now the gem uses unbinded Active Record queries in error descriptions. For example, when your query contains arguments, the error message will look like
87
-
88
- ```ruby
89
- require "rspec-sqlimit"
90
-
91
- RSpec.describe "N+1 safety" do
92
- it "doesn't send unnecessary requests to db" do
93
- expect { User.create(name: "Joe") }.not_to exceed_query_limit(1)
71
+ expect { User.create name: "Joe" }.not_to exceed_query_limit(1).with(/^INSERT/)
94
72
  end
95
73
  end
96
74
  ```
@@ -101,11 +79,11 @@ Failure/Error: expect { User.create }.not_to exceed_query_limit(0).with(/INSERT/
101
79
  Expected to run maximum 0 queries that match (?-mix:INSERT)
102
80
  The following 1 queries were invoked among others (see mark ->):
103
81
  1) begin transaction (0.072 ms)
104
- -> 2) INSERT INTO "users" ("name") VALUES (?) (0.368 ms)
82
+ -> 2) INSERT INTO "users" ("name") VALUES (?); ["Joe"] (0.368 ms)
105
83
  3) commit transaction (147.559 ms)
106
84
  ```
107
85
 
108
- This is because [Active Record instrumentation hook][hook] keeps a query and bindings separately (under `:sql` and `:binds` keys). So the challenge is **to bind arguments to the query** in the report to make a debugging a bit simpler.
86
+ In the last example you can see that binded values are shown after the query following the Rails convention.
109
87
 
110
88
  ## License
111
89
 
@@ -124,3 +102,4 @@ The gem is available as open source under the terms of the [MIT License](http://
124
102
  [notification]: http://api.rubyonrails.org/classes/ActiveSupport/Notifications.html
125
103
  [instrumentation]: http://guides.rubyonrails.org/active_support_instrumentation.html
126
104
  [hook]: http://guides.rubyonrails.org/active_support_instrumentation.html#sql-active-record
105
+ [hydra]: https://evilmartians.com/chronicles/fighting-the-hydra-of-n-plus-one-queries
data/Rakefile CHANGED
@@ -8,6 +8,6 @@ load "spec/dummy/Rakefile"
8
8
 
9
9
  # Declares gem's own tasks.
10
10
  desc "Runs test suite."
11
- task default: %w(dummy:db:migrate) do
11
+ task default: %w(dummy:db:create dummy:db:migrate) do
12
12
  system "bundle exec rspec spec"
13
13
  end
@@ -31,7 +31,11 @@ module RSpec::SQLimit
31
31
  def callback
32
32
  @callback ||= lambda do |_name, start, finish, _message_id, values|
33
33
  return if %w(CACHE SCHEMA).include? values[:name]
34
- queries << { sql: values[:sql], duration: (finish - start) * 1_000 }
34
+ queries << {
35
+ sql: values[:sql],
36
+ duration: (finish - start) * 1_000,
37
+ binds: values[:type_casted_binds]
38
+ }
35
39
  end
36
40
  end
37
41
  end
@@ -28,7 +28,8 @@ module RSpec::SQLimit
28
28
 
29
29
  def line(query, index)
30
30
  prefix = (matcher && query[:sql] =~ matcher) ? "->" : " "
31
- "#{prefix} #{index + 1}) #{query[:sql]} (#{query[:duration].round(3)} ms)"
31
+ binds = query[:binds].any? ? "; #{query[:binds]} " : ''
32
+ "#{prefix} #{index + 1}) #{query[:sql]}#{binds} (#{query[:duration].round(3)} ms)"
32
33
  end
33
34
  end
34
35
  end
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |gem|
2
2
  gem.name = "rspec-sqlimit"
3
- gem.version = "0.0.1"
3
+ gem.version = "0.0.2"
4
4
  gem.author = "Andrew Kozin (nepalez)"
5
5
  gem.email = "andrew.kozin@gmail.com"
6
6
  gem.homepage = "https://github.com/nepalez/rspec-sqlimit"
@@ -1,4 +1,4 @@
1
- class CreateUsers < ActiveRecord::Migration
1
+ class CreateUsers < ActiveRecord::Migration[4.2]
2
2
  def change
3
3
  create_table :users
4
4
  end
@@ -0,0 +1,43 @@
1
+ require "spec_helper"
2
+
3
+ describe RSpec::SQLimit::Reporter do
4
+ subject { described_class.new(counter) }
5
+
6
+ context 'no params were passed to the query' do
7
+ let(:counter) { RSpec::SQLimit::Counter[/CREATE/, Proc.new{ User.create }] }
8
+
9
+ it "doesn't print binds" do
10
+ # INSERT INTO "users" DEFAULT VALUES (0.284 ms)
11
+ expect(subject.call).to include("DEFAULT VALUES")
12
+ end
13
+ end
14
+
15
+ context 'query contains params' do
16
+ context 'nil was passed as param' do
17
+ let(:counter) { RSpec::SQLimit::Counter[/CREATE/, Proc.new{ User.create(id: nil) }] }
18
+
19
+ it "doesn't print binds" do
20
+ # INSERT INTO "users" DEFAULT VALUES (0.284 ms)
21
+ expect(subject.call).to include("DEFAULT VALUES")
22
+ end
23
+ end
24
+
25
+ context 'single param was passed' do
26
+ let(:counter) { RSpec::SQLimit::Counter[/CREATE/, Proc.new{ User.create(id: 1) }] }
27
+
28
+ it 'prints param as an array with one element' do
29
+ # INSERT INTO "users" ("id") VALUES (?); [1] (0.234 ms)
30
+ expect(subject.call).to include("VALUES (?); [1]")
31
+ end
32
+ end
33
+
34
+ context 'array was passed as a param' do
35
+ let(:counter) { RSpec::SQLimit::Counter[/SELECT/, Proc.new{ User.where(id: [1, 2, 3]).to_a }] }
36
+
37
+ it 'prints all params' do
38
+ # SELECT "users".* FROM "users" WHERE "users"."id" IN (1, 2, 3) (0.17 ms))
39
+ expect(subject.call).to include("IN (1, 2, 3)")
40
+ end
41
+ end
42
+ end
43
+ end
@@ -6,6 +6,14 @@ describe "exceed_query_limit" do
6
6
  expect { User.new }.not_to exceed_query_limit(0)
7
7
  end
8
8
 
9
+ it "works when nil is used as a parameter" do
10
+ expect { User.create id: nil }.to exceed_query_limit(0)
11
+ end
12
+
13
+ it "works when array is used as a restriction" do
14
+ expect { (User.where id: [1, 2, 3]).to_a }.to exceed_query_limit(0)
15
+ end
16
+
9
17
  it "works when actual number of queries is below the limit" do
10
18
  expect { User.create }.not_to exceed_query_limit(3)
11
19
  end
@@ -20,6 +28,14 @@ describe "exceed_query_limit" do
20
28
  expect { User.new }.not_to exceed_query_limit(0).with(/INSERT/)
21
29
  end
22
30
 
31
+ it "works when nil is used as a parameter" do
32
+ expect { User.create id: nil }.to exceed_query_limit(0).with(/INSERT/)
33
+ end
34
+
35
+ it "works when array is used as a restriction" do
36
+ expect { (User.where id: [1, 2, 3]).to_a }.to exceed_query_limit(0).with(/SELECT/)
37
+ end
38
+
23
39
  it "works when actual number of queries is below the limit" do
24
40
  expect { User.create }.not_to exceed_query_limit(1).with(/INSERT/)
25
41
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rspec-sqlimit
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Kozin (nepalez)
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-02-12 00:00:00.000000000 Z
11
+ date: 2017-06-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -120,12 +120,14 @@ executables: []
120
120
  extensions: []
121
121
  extra_rdoc_files:
122
122
  - README.md
123
+ - CHANGELOG.md
123
124
  files:
124
125
  - ".codeclimate.yml"
125
126
  - ".gitignore"
126
127
  - ".rspec"
127
128
  - ".rubocop.yml"
128
129
  - ".travis.yml"
130
+ - CHANGELOG.md
129
131
  - Gemfile
130
132
  - LICENSE.txt
131
133
  - README.md
@@ -141,9 +143,9 @@ files:
141
143
  - spec/dummy/config/environment.rb
142
144
  - spec/dummy/db/migrate/20170211104800_create_users.rb
143
145
  - spec/dummy/db/schema.rb
144
- - spec/dummy/db/test.sqlite3
145
146
  - spec/dummy/lib/dummy.rb
146
147
  - spec/dummy/lib/dummy/application.rb
148
+ - spec/rspec/sqlimit/reporter_spec.rb
147
149
  - spec/rspec/sqlimit_spec.rb
148
150
  - spec/spec_helper.rb
149
151
  homepage: https://github.com/nepalez/rspec-sqlimit
@@ -177,8 +179,8 @@ test_files:
177
179
  - spec/dummy/config/environment.rb
178
180
  - spec/dummy/db/migrate/20170211104800_create_users.rb
179
181
  - spec/dummy/db/schema.rb
180
- - spec/dummy/db/test.sqlite3
181
182
  - spec/dummy/lib/dummy.rb
182
183
  - spec/dummy/lib/dummy/application.rb
184
+ - spec/rspec/sqlimit/reporter_spec.rb
183
185
  - spec/rspec/sqlimit_spec.rb
184
186
  - spec/spec_helper.rb
Binary file