rspec-sqlimit 0.0.1 → 0.0.2

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: 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