database_plumber 1.0.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 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