database_plumber 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 56ed59f538667d495b0d65ff3f41123960c24ad3
4
+ data.tar.gz: 176d79d1c384c06e07c1545e80c2d48c328fb55a
5
+ SHA512:
6
+ metadata.gz: ccdc5f2947c9ae74775e53f096d8c1576331101e54e5f62dfd90f2b4e7798b9a1374ac585da556dac6eb5f0764af911ad6deffe9bb196cce44b55e0e718123d9
7
+ data.tar.gz: fb8dab7896d3c5da4fc595fdc6d0736cba4f48e871b82f6c0eeb488f0a078803b7bf94bd519608da69c90acf1a34b7690a3097cf4854104cd7795ac711472a34
data/.gitignore ADDED
@@ -0,0 +1,14 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
12
+ *.o
13
+ *.a
14
+ mkmf.log
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --color
2
+ --require spec_helper
3
+ --format documentation
data/.ruby-gemset ADDED
@@ -0,0 +1 @@
1
+ database_plumber
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ ruby-2.1.2
data/.travis.yml ADDED
@@ -0,0 +1,6 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.1.3
4
+
5
+ script:
6
+ - bundle exec rspec
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in database_plumber.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2015 Barry Gordon
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,151 @@
1
+ # DatabasePlumber [![Build Status](https://travis-ci.org/brrygrdn/database_plumber.svg?branch=v0.0.1)](https://travis-ci.org/brrygrdn/database_plumber)
2
+
3
+ A common problem in test suites for large [Rails][rails] applications is that,
4
+ as they mature, balancing test speed and complexity often results in heavy use
5
+ of tools like [FactoryGirl][factorygirl] and [DatabaseCleaner][databasecleaner].
6
+
7
+ These are powerful and useful tools, but over time it often becomes evident that
8
+ large factories can create and orphan many rows in the database; combine with the
9
+ need for non-transactional database maintenance during [Capybara][capybara] tests
10
+ and its very easy to be plagued by mystery guests.
11
+
12
+ DatabasePlumber is a quick utility that checks for rows left after an example
13
+ group has been executed, publishes a report and cleans up.
14
+
15
+ ## Why use this?
16
+
17
+ Well, for starters, it acts as a quick sticking plaster on the problem of mystery
18
+ guests, giving you back confidence in your CI runs in the short term.
19
+
20
+ Long-term, it removes the fear from optimizing the persistence of objects using
21
+ [RSpec][rspec] `before(:all)` blocks by making it clear when you, or your factories
22
+ have not cleaned up properly after.
23
+
24
+ ## Installation
25
+
26
+ Add this line to your application's Gemfile:
27
+
28
+ ```ruby
29
+ gem 'database_plumber', github: 'brrygrdn/database_plumber'
30
+ ```
31
+
32
+ And then execute:
33
+
34
+ $ bundle
35
+
36
+
37
+ ## Usage
38
+
39
+ To get started, add the following lines to your `spec_helper.rb`
40
+
41
+ ```ruby
42
+ RSpec.configure do |config|
43
+
44
+ ...
45
+
46
+ config.after(:each) do |example|
47
+ DatabaseCleaner.clean
48
+ # Notify DatabasePlumber of each example after it has been executed
49
+ DatabasePlumber.log example
50
+ end
51
+
52
+ config.after(:all) do
53
+ # Perform the report after each example group
54
+ DatabasePlumber.inspect
55
+ end
56
+
57
+ ...
58
+
59
+ end
60
+ ```
61
+
62
+ Run your tests as normal, and you'll see a report after any examples:
63
+
64
+ ```
65
+ > bundle exec rspec spec/models/
66
+ .....
67
+ #### Leaking Test
68
+
69
+ The spec './spec/models/foo_spec.rb' leaves
70
+ the following rows in the database:
71
+
72
+ - 1 row(s) for the Foo model
73
+ - 5 row(s) for the Bar model
74
+
75
+ #### What now?
76
+
77
+ If you are using let! or before(:all) please ensure that you use a
78
+ corresponding after(:all) block to clean up these rows.
79
+
80
+ ..........
81
+
82
+ Finished in 3.14159 seconds
83
+ 15 examples, 0 failures
84
+
85
+ Randomized with seed 17015
86
+ ```
87
+
88
+ ### Ignoring Models
89
+
90
+ You may have some models that you don't want to report on, for example a configuration
91
+ table that is seeded or loaded with fixtures as part of test suite setup.
92
+
93
+ ```ruby
94
+ config.after(:all) do
95
+ # Perform the report after each example group
96
+ DatabasePlumber.inspect ignored_models: [Bar, Baz]
97
+ end
98
+ ```
99
+
100
+ ### Ignoring Databases
101
+
102
+ You may have models in your application backed by multiple adapters, some of which
103
+ may be throw-away after each example group e.g. using SQLite for anonymous models
104
+
105
+ To exclude all models from a given adapter, you can add the following:
106
+
107
+ ```ruby
108
+ config.after(:all) do
109
+ # Perform the report after each example group
110
+ DatabasePlumber.inspect ignored_adapters: [:sqlite]
111
+ end
112
+ ```
113
+
114
+ If you are unsure of which adapter to ignore, you can check via the Rails console:
115
+
116
+ ```ruby
117
+ > Foo.connection.adapter_name
118
+ 'PostgreSQL'
119
+ # The corresponding symbol to use is :postgresql
120
+ ```
121
+
122
+ ### Halting Tests on a Leak
123
+
124
+ When debugging a suite with several mystery guests, you can halt immediately
125
+ after each leak.
126
+
127
+ ```ruby
128
+ config.after(:all) do
129
+ # Perform the report after each example group
130
+ DatabasePlumber.inspect ignored_models: [Bar, Baz],
131
+ ignored_adapters: [:sqlite],
132
+ brutal: true
133
+ end
134
+ ```
135
+
136
+ This is also useful if your test suite is problem-free and you would like ensure it
137
+ stays that way.
138
+
139
+ ## Contributing
140
+
141
+ 1. Fork it ( https://github.com/brrygrdn/database_plumber/fork )
142
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
143
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
144
+ 4. Push to the branch (`git push origin my-new-feature`)
145
+ 5. Create a new Pull Request
146
+
147
+ [rails]: https://github.com/rails/rails
148
+ [factorygirl]: https://github.com/thoughtbot/factory_girl
149
+ [databasecleaner]: https://github.com/DatabaseCleaner/database_cleaner
150
+ [capybara]: https://github.com/jnicklas/capybara
151
+ [rspec]: https://github.com/rspec/rspec
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require 'bundler/gem_tasks'
@@ -0,0 +1,27 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'database_plumber/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "database_plumber"
8
+ spec.version = DatabasePlumber::VERSION
9
+ spec.authors = ["Barry Gordon", "David Kennedy"]
10
+ spec.email = ["hello@barrygordon.co.uk", "dave@dkennedy.org"]
11
+ spec.summary = %q{Finds leaky ActiveRecord models in your specs.}
12
+ spec.homepage = "https://github.com/brrygrdn/database_plumber"
13
+ spec.license = "MIT"
14
+
15
+ spec.files = `git ls-files -z`.split("\x0")
16
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
17
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
18
+ spec.require_paths = ["lib"]
19
+
20
+ spec.add_development_dependency "bundler", "~> 1.7"
21
+ spec.add_development_dependency "rake", "~> 10.0"
22
+ spec.add_development_dependency "pry"
23
+
24
+ spec.add_runtime_dependency "activerecord"
25
+ spec.add_runtime_dependency "rspec"
26
+ spec.add_runtime_dependency "highline"
27
+ end
@@ -0,0 +1,57 @@
1
+ module DatabasePlumber
2
+ class LeakFinder
3
+ class InvalidModelError < StandardError ; end
4
+
5
+ IGNORED_AR_INTERNALS = [ActiveRecord::SchemaMigration]
6
+ private_constant :IGNORED_AR_INTERNALS
7
+
8
+ def self.inspect(options = {})
9
+ new(options).inspect
10
+ end
11
+
12
+ def initialize(options)
13
+ @ignored_models = (options[:ignored_models] || []) + IGNORED_AR_INTERNALS
14
+ @ignored_adapters = options[:ignored_adapters] || []
15
+ end
16
+
17
+ def inspect
18
+ filtered_models.each_with_object({}) do |model, results|
19
+ records = count_for(model)
20
+ if records > 0
21
+ results[model.to_s] = records
22
+ mop_up(model)
23
+ end
24
+ results
25
+ end
26
+ end
27
+
28
+ private
29
+
30
+ def count_for(model)
31
+ return 0 if no_table?(model)
32
+ model.count
33
+ rescue ActiveRecord::StatementInvalid
34
+ raise InvalidModelError, "#{model} does not have a valid table definition"
35
+ end
36
+
37
+ def mop_up(model)
38
+ model.destroy_all
39
+ end
40
+
41
+ def no_table?(model)
42
+ model.abstract_class? || @ignored_adapters.include?(model.connection.adapter_name.downcase.to_sym)
43
+ end
44
+
45
+ def filtered_models
46
+ model_space.reject(&method(:excluded_model?))
47
+ end
48
+
49
+ def excluded_model?(model)
50
+ @ignored_models.include?(model) || model.name =~ /^HABTM_/
51
+ end
52
+
53
+ def model_space
54
+ ActiveRecord::Base.descendants
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,35 @@
1
+ require 'highline'
2
+
3
+ module DatabasePlumber
4
+ class Report
5
+ def self.on(example, leaks)
6
+ puts <<-REPORT.strip_heredoc
7
+
8
+ #{HighLine.color('#### Leaking Test', :red)}
9
+
10
+ The spec '#{HighLine.color(spec_path_for(example), :red, :underline)}' leaves
11
+ the following rows in the database:
12
+
13
+ REPORT
14
+
15
+ leaks.each(&method(:print_leak))
16
+
17
+ puts <<-REPORT.strip_heredoc
18
+
19
+ #{HighLine.color('#### What now?', :yellow)}
20
+
21
+ If you are using #{HighLine.color('let!', :yellow)} or #{HighLine.color('before(:all)', :yellow)} please ensure that you use a
22
+ corresponding #{HighLine.color('after(:all)', :yellow)} block to clean up these rows.
23
+
24
+ REPORT
25
+ end
26
+
27
+ private_class_method def self.print_leak(model, count)
28
+ puts " - #{HighLine.color(count.to_s, :blue)} row(s) for the #{model} model \n"
29
+ end
30
+
31
+ private_class_method def self.spec_path_for(example)
32
+ example.metadata[:example_group][:file_path]
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,3 @@
1
+ module DatabasePlumber
2
+ VERSION = '1.0.0'
3
+ end
@@ -0,0 +1,19 @@
1
+ require 'active_record'
2
+
3
+ require 'database_plumber/leak_finder'
4
+ require 'database_plumber/report'
5
+ require 'database_plumber/version'
6
+
7
+ module DatabasePlumber
8
+ def self.log(example)
9
+ @example = example
10
+ end
11
+
12
+ def self.inspect(options = {})
13
+ leaks = LeakFinder.inspect(options)
14
+ unless leaks.empty?
15
+ Report.on @example, leaks
16
+ exit! if options[:brutal]
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,129 @@
1
+ RSpec.describe DatabasePlumber::LeakFinder do
2
+ let(:normal_connection) { double(:connection, adapter_name: 'NotSQLite') }
3
+ let(:ignored_connection) { double(:connection, adapter_name: 'SQLite') }
4
+
5
+ let(:happy_model) { double(:happy, name: 'Happy', abstract_class?: nil, connection: normal_connection, count: 0) }
6
+ let(:leaky_model) { double(:leaky, name: 'Leaky', abstract_class?: nil, connection: normal_connection, count: 1) }
7
+ let(:abstract_model) { double(:abstract, name: 'Abstract', abstract_class?: true, connection: normal_connection, count: 2) }
8
+ let(:ignored_model) { double(:ignored, name: 'Ignored', abstract_class?: nil, connection: normal_connection, count: 3) }
9
+ let(:ignored_adapter_model) { double(:anon, name: 'Anon', abstract_class?: nil, connection: ignored_connection, count: 4) }
10
+ let(:join_model_stub) { double(:habtm, name: 'HABTM_Things', abstract_class?: nil, connection: normal_connection, count: 5) }
11
+
12
+ let(:globally_ignored_models) { [ActiveRecord::SchemaMigration] }
13
+
14
+ let(:model_space) { [happy_model, leaky_model, ignored_model, abstract_model, ignored_adapter_model, join_model_stub] | globally_ignored_models }
15
+
16
+ before(:each) do
17
+ model_space.each do |model|
18
+ allow(model).to receive(:destroy_all)
19
+ end
20
+ allow(ActiveRecord::Base).to receive(:descendants) { model_space }
21
+ end
22
+
23
+ describe '.inspect' do
24
+ context 'with no params' do
25
+ let(:expected_leaks) do
26
+ {
27
+ leaky_model.to_s => 1,
28
+ ignored_model.to_s => 3,
29
+ ignored_adapter_model.to_s => 4
30
+ }
31
+ end
32
+
33
+ before(:each) { @leaks = described_class.inspect }
34
+
35
+ it { expect(@leaks).to eql(expected_leaks) }
36
+
37
+ it { expect(ActiveRecord::SchemaMigration).not_to have_received(:destroy_all) }
38
+
39
+ it { expect(happy_model).not_to have_received(:destroy_all) }
40
+ it { expect(leaky_model).to have_received(:destroy_all) }
41
+
42
+ it { expect(ignored_model).to have_received(:destroy_all) }
43
+ it { expect(ignored_adapter_model).to have_received(:destroy_all) }
44
+
45
+ it { expect(join_model_stub).not_to have_received(:destroy_all) }
46
+ end
47
+
48
+ context 'with an ignored model' do
49
+ let(:options_params) do
50
+ {
51
+ ignored_models: [ignored_model]
52
+ }
53
+ end
54
+
55
+ let(:expected_leaks) do
56
+ {
57
+ leaky_model.to_s => 1,
58
+ ignored_adapter_model.to_s => 4
59
+ }
60
+ end
61
+
62
+ before(:each) { @leaks = described_class.inspect(options_params) }
63
+
64
+ it { expect(@leaks).to eql(expected_leaks) }
65
+
66
+ it { expect(ActiveRecord::SchemaMigration).not_to have_received(:destroy_all) }
67
+
68
+ it { expect(happy_model).not_to have_received(:destroy_all) }
69
+ it { expect(leaky_model).to have_received(:destroy_all) }
70
+
71
+ it { expect(ignored_model).not_to have_received(:destroy_all) }
72
+ it { expect(ignored_adapter_model).to have_received(:destroy_all) }
73
+
74
+ it { expect(join_model_stub).not_to have_received(:destroy_all) }
75
+ end
76
+
77
+ context 'with an ignored adapter' do
78
+ let(:options_params) do
79
+ {
80
+ ignored_adapters: [:sqlite]
81
+ }
82
+ end
83
+
84
+ let(:expected_leaks) do
85
+ {
86
+ leaky_model.to_s => 1,
87
+ ignored_model.to_s => 3
88
+ }
89
+ end
90
+
91
+ before(:each) { @leaks = described_class.inspect(options_params) }
92
+
93
+ it { expect(@leaks).to eql(expected_leaks) }
94
+
95
+ it { expect(ActiveRecord::SchemaMigration).not_to have_received(:destroy_all) }
96
+
97
+ it { expect(happy_model).not_to have_received(:destroy_all) }
98
+ it { expect(leaky_model).to have_received(:destroy_all) }
99
+
100
+ it { expect(ignored_model).to have_received(:destroy_all) }
101
+ it { expect(ignored_adapter_model).not_to have_received(:destroy_all) }
102
+
103
+ it { expect(join_model_stub).not_to have_received(:destroy_all) }
104
+ end
105
+
106
+ context 'with no leaking models in scope' do
107
+ let(:options_params) do
108
+ {
109
+ ignored_models: [ignored_model, leaky_model],
110
+ ignored_adapters: [:sqlite]
111
+ }
112
+ end
113
+
114
+ before(:each) { @leaks = described_class.inspect(options_params) }
115
+
116
+ it { expect(@leaks).to be_empty }
117
+
118
+ it { expect(ActiveRecord::SchemaMigration).not_to have_received(:destroy_all) }
119
+
120
+ it { expect(happy_model).not_to have_received(:destroy_all) }
121
+ it { expect(leaky_model).not_to have_received(:destroy_all) }
122
+
123
+ it { expect(ignored_model).not_to have_received(:destroy_all) }
124
+ it { expect(ignored_adapter_model).not_to have_received(:destroy_all) }
125
+
126
+ it { expect(join_model_stub).not_to have_received(:destroy_all) }
127
+ end
128
+ end
129
+ end
@@ -0,0 +1,31 @@
1
+ RSpec.describe DatabasePlumber do
2
+ let(:report_class) { DatabasePlumber::Report }
3
+
4
+ let(:current_example) { self }
5
+
6
+ before(:each) do
7
+ allow(report_class).to receive(:on)
8
+ described_class.log current_example
9
+ end
10
+
11
+ context 'with no leaks' do
12
+ before(:each) do
13
+ described_class.inspect
14
+ end
15
+
16
+ it { expect(report_class).not_to have_received(:on) }
17
+ end
18
+
19
+ context 'with leaks' do
20
+ let(:leaks) do
21
+ { 'Foo' => 5 }
22
+ end
23
+
24
+ before(:each) do
25
+ allow(DatabasePlumber::LeakFinder).to receive(:inspect) { leaks }
26
+ described_class.inspect
27
+ end
28
+
29
+ it { expect(report_class).to have_received(:on).with(current_example, leaks) }
30
+ end
31
+ end
@@ -0,0 +1,31 @@
1
+ require 'pry'
2
+
3
+ require 'bundler/setup'
4
+ Bundler.setup
5
+
6
+ require 'database_plumber'
7
+
8
+ RSpec.configure do |config|
9
+ config.expect_with :rspec do |expectations|
10
+ expectations.include_chain_clauses_in_custom_matcher_descriptions = true
11
+ end
12
+
13
+ config.mock_with :rspec do |mocks|
14
+ mocks.verify_partial_doubles = true
15
+ end
16
+
17
+ config.filter_run :focus
18
+ config.run_all_when_everything_filtered = true
19
+
20
+ config.disable_monkey_patching!
21
+
22
+ config.warnings = true
23
+
24
+ config.default_formatter = 'doc' if config.files_to_run.one?
25
+
26
+ config.profile_examples = 10
27
+
28
+ config.order = :random
29
+
30
+ Kernel.srand config.seed
31
+ end
metadata ADDED
@@ -0,0 +1,150 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: database_plumber
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Barry Gordon
8
+ - David Kennedy
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2016-03-04 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: bundler
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - "~>"
19
+ - !ruby/object:Gem::Version
20
+ version: '1.7'
21
+ type: :development
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - "~>"
26
+ - !ruby/object:Gem::Version
27
+ version: '1.7'
28
+ - !ruby/object:Gem::Dependency
29
+ name: rake
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - "~>"
33
+ - !ruby/object:Gem::Version
34
+ version: '10.0'
35
+ type: :development
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - "~>"
40
+ - !ruby/object:Gem::Version
41
+ version: '10.0'
42
+ - !ruby/object:Gem::Dependency
43
+ name: pry
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ version: '0'
49
+ type: :development
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ version: '0'
56
+ - !ruby/object:Gem::Dependency
57
+ name: activerecord
58
+ requirement: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ version: '0'
63
+ type: :runtime
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ - !ruby/object:Gem::Dependency
71
+ name: rspec
72
+ requirement: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - ">="
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ type: :runtime
78
+ prerelease: false
79
+ version_requirements: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - ">="
82
+ - !ruby/object:Gem::Version
83
+ version: '0'
84
+ - !ruby/object:Gem::Dependency
85
+ name: highline
86
+ requirement: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ - - ">="
89
+ - !ruby/object:Gem::Version
90
+ version: '0'
91
+ type: :runtime
92
+ prerelease: false
93
+ version_requirements: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - ">="
96
+ - !ruby/object:Gem::Version
97
+ version: '0'
98
+ description:
99
+ email:
100
+ - hello@barrygordon.co.uk
101
+ - dave@dkennedy.org
102
+ executables: []
103
+ extensions: []
104
+ extra_rdoc_files: []
105
+ files:
106
+ - ".gitignore"
107
+ - ".rspec"
108
+ - ".ruby-gemset"
109
+ - ".ruby-version"
110
+ - ".travis.yml"
111
+ - Gemfile
112
+ - LICENSE.txt
113
+ - README.md
114
+ - Rakefile
115
+ - database_plumber.gemspec
116
+ - lib/database_plumber.rb
117
+ - lib/database_plumber/leak_finder.rb
118
+ - lib/database_plumber/report.rb
119
+ - lib/database_plumber/version.rb
120
+ - spec/lib/database_plumber/leak_finder_spec.rb
121
+ - spec/lib/database_plumber_spec.rb
122
+ - spec/spec_helper.rb
123
+ homepage: https://github.com/brrygrdn/database_plumber
124
+ licenses:
125
+ - MIT
126
+ metadata: {}
127
+ post_install_message:
128
+ rdoc_options: []
129
+ require_paths:
130
+ - lib
131
+ required_ruby_version: !ruby/object:Gem::Requirement
132
+ requirements:
133
+ - - ">="
134
+ - !ruby/object:Gem::Version
135
+ version: '0'
136
+ required_rubygems_version: !ruby/object:Gem::Requirement
137
+ requirements:
138
+ - - ">="
139
+ - !ruby/object:Gem::Version
140
+ version: '0'
141
+ requirements: []
142
+ rubyforge_project:
143
+ rubygems_version: 2.2.2
144
+ signing_key:
145
+ specification_version: 4
146
+ summary: Finds leaky ActiveRecord models in your specs.
147
+ test_files:
148
+ - spec/lib/database_plumber/leak_finder_spec.rb
149
+ - spec/lib/database_plumber_spec.rb
150
+ - spec/spec_helper.rb