database_resetter 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +11 -0
- data/HISTORY.markdown +5 -0
- data/LICENCE.markdown +31 -0
- data/README.markdown +177 -0
- data/Rakefile +27 -0
- data/VERSION +1 -0
- data/config/cucumber.yml +9 -0
- data/config/darcs.boring +118 -0
- data/features/descriptions/change_environment.feature +17 -0
- data/features/descriptions/database_resetter.feature +24 -0
- data/features/descriptions/different_web_frameworks.feature +24 -0
- data/features/descriptions/no_migrations.feature +19 -0
- data/features/step_definitions/database_resetter_steps.rb +125 -0
- data/features/support/env.rb +8 -0
- data/lib/database_resetter.rb +86 -0
- metadata +86 -0
data/Gemfile
ADDED
data/HISTORY.markdown
ADDED
data/LICENCE.markdown
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
# Licence
|
2
|
+
|
3
|
+
This software is released under the Simplified BSD Licence.
|
4
|
+
|
5
|
+
## database\_resetter licence
|
6
|
+
|
7
|
+
Copyright 2010 PatchSpace Ltd. All rights reserved.
|
8
|
+
|
9
|
+
Redistribution and use in source and binary forms, with or without modification, are
|
10
|
+
permitted provided that the following conditions are met:
|
11
|
+
|
12
|
+
1. Redistributions of source code must retain the above copyright notice, this list of
|
13
|
+
conditions and the following disclaimer.
|
14
|
+
|
15
|
+
2. Redistributions in binary form must reproduce the above copyright notice, this list
|
16
|
+
of conditions and the following disclaimer in the documentation and/or other materials
|
17
|
+
provided with the distribution.
|
18
|
+
|
19
|
+
THIS SOFTWARE IS PROVIDED BY PATCHSPACE LTD ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
20
|
+
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
21
|
+
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL PATCHSPACE LTD OR
|
22
|
+
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
23
|
+
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
24
|
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
25
|
+
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
26
|
+
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
27
|
+
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
28
|
+
|
29
|
+
The views and conclusions contained in the software and documentation are those of the
|
30
|
+
authors and should not be interpreted as representing official policies, either expressed
|
31
|
+
or implied, of PatchSpace Ltd.
|
data/README.markdown
ADDED
@@ -0,0 +1,177 @@
|
|
1
|
+
# database\_resetter
|
2
|
+
|
3
|
+
## Introduction
|
4
|
+
|
5
|
+
### What does it do?
|
6
|
+
|
7
|
+
database\_resetter is a small gem to handle automatically resetting
|
8
|
+
your test databases when developing a Ruby web app.
|
9
|
+
|
10
|
+
### Why do I want it?
|
11
|
+
|
12
|
+
Because you're sick of seeing "No column XXX in table YYY" or some such,
|
13
|
+
because your test database is out of sync with your migrations. If you're
|
14
|
+
making a lot of database changes, this can save you a fair bit of time.
|
15
|
+
|
16
|
+
I've used this code almost unmodified in all of my clients' projects over
|
17
|
+
the last year or two. Pretty much everyone that's seen it has said
|
18
|
+
it looked pretty handy, so I've bundled it up as a gem.
|
19
|
+
|
20
|
+
### How does it work?
|
21
|
+
|
22
|
+
database\_resetter writes timestamp files into _log/database\_resetter_
|
23
|
+
that track when the database was last reset. It tracks them:
|
24
|
+
|
25
|
+
* per environment (eg test, cucumber)
|
26
|
+
* per hostname
|
27
|
+
|
28
|
+
Per-hostname tracking is done in case you use Dropbox/JungleDisk etc to sync
|
29
|
+
code between machines. (Note: there are no features/specs to prove this works.)
|
30
|
+
|
31
|
+
What _isn't_ tracked is what directory / SCM branch you're in. So if you switch
|
32
|
+
to a different working copy folder, or change eg Git branch, database\_resetter
|
33
|
+
may not run the migrations. If you'd like this feature please contact me.
|
34
|
+
|
35
|
+
_The easiest way to make database\_resetter run is to touch a migration file._
|
36
|
+
|
37
|
+
### How is database\_resetter different from database\_cleaner?
|
38
|
+
|
39
|
+
Ben Mabey wrote [database\_cleaner](http://github.com/bmabey/database_cleaner) to
|
40
|
+
help with emptying a database between individual test cases. database\_resetter is
|
41
|
+
designed to get the initial schema of a database in place before any test cases run.
|
42
|
+
|
43
|
+
Basically, you want both :-)
|
44
|
+
|
45
|
+
|
46
|
+
## Instructions
|
47
|
+
|
48
|
+
If you're working on a Rails app, and your tests are good to go after a
|
49
|
+
`rake db:reset`, then place the following code somewhere that
|
50
|
+
will get executed once per test run:
|
51
|
+
|
52
|
+
DatabaseResetter.new.reset_if_required
|
53
|
+
|
54
|
+
Note: there are no features to prove this default call actually works :) I've
|
55
|
+
always specified the options explicitly myself. But the defaults should work with
|
56
|
+
Rails. If not, let me know.
|
57
|
+
|
58
|
+
For instructions on specifying the options, see below.
|
59
|
+
|
60
|
+
### Changing the Rake task
|
61
|
+
|
62
|
+
If (like me), you don't use _schema.rb_ to regenerate databases,
|
63
|
+
you'll need your own Rake task. I use one called `rake db:rebuild`,
|
64
|
+
which is currently:
|
65
|
+
|
66
|
+
desc "Reset and re-migrate the database"
|
67
|
+
task :rebuild do
|
68
|
+
Rake::Task["db:drop"].invoke
|
69
|
+
Rake::Task["db:create"].invoke
|
70
|
+
Rake::Task["db:migrate"].invoke
|
71
|
+
end
|
72
|
+
|
73
|
+
To override the default command, specify the `:command_pattern` option:
|
74
|
+
|
75
|
+
DatabaseResetter.new(
|
76
|
+
:command_pattern => "rake db:rebuild RAILS_ENV=%ENV%"
|
77
|
+
).reset_if_required
|
78
|
+
|
79
|
+
See below for a description of `%ENV%`.
|
80
|
+
|
81
|
+
### Using a different framework
|
82
|
+
|
83
|
+
If you use a different web framework, you may have to specify a different
|
84
|
+
environment variable to switch the framework environment (eg `MERB_ENV`
|
85
|
+
or `RACK_ENV`). To override this, specify both `:command_pattern` and
|
86
|
+
`:environment`, eg:
|
87
|
+
|
88
|
+
DatabaseResetter.new(
|
89
|
+
:environment => ENV["MERB_ENV"],
|
90
|
+
:command_pattern => "rake db:reset MERB_ENV=%ENV%"
|
91
|
+
).reset_if_required
|
92
|
+
|
93
|
+
You may also need to specify a different migration file directory to watch, eg:
|
94
|
+
|
95
|
+
DatabaseResetter.new(
|
96
|
+
:migration_directory => "schema/migrations"
|
97
|
+
).reset_if_required
|
98
|
+
|
99
|
+
(You can, of course, combine all three.)
|
100
|
+
|
101
|
+
### RSpec
|
102
|
+
|
103
|
+
Put the call to `DatabaseResetter#reset_if_required` in _spec/spec\_helper.rb_.
|
104
|
+
|
105
|
+
### Cucumber
|
106
|
+
|
107
|
+
Put the call to `DatabaseResetter#reset_if_required` in
|
108
|
+
_features/support/env.rb_.
|
109
|
+
|
110
|
+
### Spork
|
111
|
+
|
112
|
+
If you use Spork, you want to call `DatabaseResetter#reset_if_required` in the
|
113
|
+
`each_run` block, eg:
|
114
|
+
|
115
|
+
Spork.each_run do
|
116
|
+
# ...
|
117
|
+
DatabaseResetter.new.reset_if_required
|
118
|
+
# ...
|
119
|
+
end
|
120
|
+
|
121
|
+
### PostgreSQL
|
122
|
+
|
123
|
+
If you use PostgreSQL, and your Rake task attempts to drop the database,
|
124
|
+
Postgres will stop you if there is a connection in place. You need to work
|
125
|
+
around this somehow. If you're using Spork, you need to divert Postgres's
|
126
|
+
eyes, eg in Rails:
|
127
|
+
|
128
|
+
Spork.each_run do
|
129
|
+
# ...
|
130
|
+
|
131
|
+
ActiveRecord::Base.establish_connection(config.merge('database' => 'postgres', 'schema_search_path' => 'public'))
|
132
|
+
DatabaseResetter.new.reset_if_required
|
133
|
+
ActiveRecord::Base.establish_connection(config)
|
134
|
+
|
135
|
+
# ...
|
136
|
+
end
|
137
|
+
|
138
|
+
If you're not using Spork, you still need to make sure you call
|
139
|
+
`DatabaseResetter#reset_if_required` before connecting to the database.
|
140
|
+
One way of doing this with Bundler is to define a Bundler group just
|
141
|
+
for database\_resetter in your Gemfile:
|
142
|
+
|
143
|
+
group :database_resetter do
|
144
|
+
gem "database_resetter"
|
145
|
+
end
|
146
|
+
|
147
|
+
And then use this to load and run database\_resetter before anything connects
|
148
|
+
to the database. eg with Rails and Cucumber, in _env.rb_:
|
149
|
+
|
150
|
+
# ...
|
151
|
+
|
152
|
+
require 'bundler'
|
153
|
+
Bundler.setup(:database_resetter)
|
154
|
+
require 'database_resetter'
|
155
|
+
DatabaseResetter.new.reset_if_required
|
156
|
+
|
157
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../config/environment')
|
158
|
+
|
159
|
+
# ...
|
160
|
+
|
161
|
+
|
162
|
+
## Bugs / Feedback
|
163
|
+
|
164
|
+
There is currently no project page for database\_resetter. If you want to report
|
165
|
+
bugs in the code or documentation, or request features, please contact me:
|
166
|
+
|
167
|
+
[ashley.moran@patchspace.co.uk](mailto:ashley.moran@patchspace.co.uk)
|
168
|
+
|
169
|
+
[PatchSpace Ltd](http://www.patchspace.co.uk/)
|
170
|
+
|
171
|
+
|
172
|
+
## Source code
|
173
|
+
|
174
|
+
database\_resetter is maintained in a darcs repository, and is currently hosted
|
175
|
+
on Patch-Tag:
|
176
|
+
|
177
|
+
[Official darcs repository](https://patch-tag.com/r/ashleymoran/database_resetter/)
|
data/Rakefile
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
require "bundler"
|
2
|
+
Bundler.setup(:default)
|
3
|
+
|
4
|
+
require "jeweler"
|
5
|
+
|
6
|
+
Jeweler::Tasks.new do |gemspec|
|
7
|
+
gemspec.name = "database_resetter"
|
8
|
+
gemspec.summary = "Automatically resets your database when migrations change"
|
9
|
+
gemspec.email = "ashley.moran@patchspace.co.uk"
|
10
|
+
gemspec.homepage = "https://patch-tag.com/repo/ashleymoran/database_resetter/"
|
11
|
+
gemspec.authors = ["Ashley Moran"]
|
12
|
+
|
13
|
+
gemspec.files.include %w[
|
14
|
+
config/**/*
|
15
|
+
lib/**/*
|
16
|
+
*.markdown
|
17
|
+
Gemfile
|
18
|
+
Rakefile
|
19
|
+
VERSION
|
20
|
+
]
|
21
|
+
gemspec.test_files.include %w[
|
22
|
+
features/**/*
|
23
|
+
spec/**/*
|
24
|
+
]
|
25
|
+
end
|
26
|
+
|
27
|
+
Jeweler::GemcutterTasks.new
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.1.0
|
data/config/cucumber.yml
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
<%
|
2
|
+
rerun = File.file?('rerun.txt') ? IO.read('rerun.txt') : ""
|
3
|
+
rerun_opts = rerun.to_s.strip.empty? ? "--format #{ENV['CUCUMBER_FORMAT'] || 'progress'} features" : "--format #{ENV['CUCUMBER_FORMAT'] || 'pretty'} #{rerun}"
|
4
|
+
requires = "--require features/support --require features/step_definitions"
|
5
|
+
std_opts = "--format #{ENV['CUCUMBER_FORMAT'] || 'progress'} --strict --tags ~@wip #{requires}"
|
6
|
+
%>
|
7
|
+
default: <%= std_opts %> features
|
8
|
+
wip: --tags @wip:3 --wip <%= requires %> features
|
9
|
+
rerun: <%= rerun_opts %> --format rerun --out rerun.txt --strict --tags ~@wip
|
data/config/darcs.boring
ADDED
@@ -0,0 +1,118 @@
|
|
1
|
+
# Boring file regexps:
|
2
|
+
|
3
|
+
### compiler and interpreter intermediate files
|
4
|
+
# haskell (ghc) interfaces
|
5
|
+
\.hi$
|
6
|
+
\.hi-boot$
|
7
|
+
\.o-boot$
|
8
|
+
# object files
|
9
|
+
\.o$
|
10
|
+
\.o\.cmd$
|
11
|
+
# profiling haskell
|
12
|
+
\.p_hi$
|
13
|
+
\.p_o$
|
14
|
+
# haskell program coverage resp. profiling info
|
15
|
+
\.tix$
|
16
|
+
\.prof$
|
17
|
+
# fortran module files
|
18
|
+
\.mod$
|
19
|
+
# linux kernel
|
20
|
+
\.ko\.cmd$
|
21
|
+
\.mod\.c$
|
22
|
+
(^|/)\.tmp_versions($|/)
|
23
|
+
# *.ko files aren't boring by default because they might
|
24
|
+
# be Korean translations rather than kernel modules
|
25
|
+
# \.ko$
|
26
|
+
# python, emacs, java byte code
|
27
|
+
\.py[co]$
|
28
|
+
\.elc$
|
29
|
+
\.class$
|
30
|
+
# objects and libraries; lo and la are libtool things
|
31
|
+
\.(obj|a|exe|so|lo|la)$
|
32
|
+
# compiled zsh configuration files
|
33
|
+
\.zwc$
|
34
|
+
# Common LISP output files for CLISP and CMUCL
|
35
|
+
\.(fas|fasl|sparcf|x86f)$
|
36
|
+
|
37
|
+
### build and packaging systems
|
38
|
+
# cabal intermediates
|
39
|
+
\.installed-pkg-config
|
40
|
+
\.setup-config
|
41
|
+
# standard cabal build dir, might not be boring for everybody
|
42
|
+
# ^dist(/|$)
|
43
|
+
# autotools
|
44
|
+
(^|/)autom4te\.cache($|/)
|
45
|
+
(^|/)config\.(log|status)$
|
46
|
+
# microsoft web expression, visual studio metadata directories
|
47
|
+
\_vti_cnf$
|
48
|
+
\_vti_pvt$
|
49
|
+
# gentoo tools
|
50
|
+
\.revdep-rebuild.*
|
51
|
+
# generated dependencies
|
52
|
+
^\.depend$
|
53
|
+
|
54
|
+
### version control systems
|
55
|
+
# cvs
|
56
|
+
(^|/)CVS($|/)
|
57
|
+
\.cvsignore$
|
58
|
+
# cvs, emacs locks
|
59
|
+
^\.#
|
60
|
+
# rcs
|
61
|
+
(^|/)RCS($|/)
|
62
|
+
,v$
|
63
|
+
# subversion
|
64
|
+
(^|/)\.svn($|/)
|
65
|
+
# mercurial
|
66
|
+
(^|/)\.hg($|/)
|
67
|
+
# git
|
68
|
+
(^|/)\.git($|/)
|
69
|
+
# bzr
|
70
|
+
\.bzr$
|
71
|
+
# sccs
|
72
|
+
(^|/)SCCS($|/)
|
73
|
+
# darcs
|
74
|
+
(^|/)_darcs($|/)
|
75
|
+
(^|/)\.darcsrepo($|/)
|
76
|
+
^\.darcs-temp-mail$
|
77
|
+
-darcs-backup[[:digit:]]+$
|
78
|
+
# gnu arch
|
79
|
+
(^|/)(\+|,)
|
80
|
+
(^|/)vssver\.scc$
|
81
|
+
\.swp$
|
82
|
+
(^|/)MT($|/)
|
83
|
+
(^|/)\{arch\}($|/)
|
84
|
+
(^|/).arch-ids($|/)
|
85
|
+
# bitkeeper
|
86
|
+
(^|/)BitKeeper($|/)
|
87
|
+
(^|/)ChangeSet($|/)
|
88
|
+
|
89
|
+
### miscellaneous
|
90
|
+
# backup files
|
91
|
+
~$
|
92
|
+
\.bak$
|
93
|
+
\.BAK$
|
94
|
+
# patch originals and rejects
|
95
|
+
\.orig$
|
96
|
+
\.rej$
|
97
|
+
# X server
|
98
|
+
\..serverauth.*
|
99
|
+
# image spam
|
100
|
+
\#
|
101
|
+
(^|/)Thumbs\.db$
|
102
|
+
# vi, emacs tags
|
103
|
+
(^|/)(tags|TAGS)$
|
104
|
+
#(^|/)\.[^/]
|
105
|
+
# core dumps
|
106
|
+
(^|/|\.)core$
|
107
|
+
# partial broken files (KIO copy operations)
|
108
|
+
\.part$
|
109
|
+
# waf files, see http://code.google.com/p/waf/
|
110
|
+
(^|/)\.waf-[[:digit:].]+-[[:digit:]]+($|/)
|
111
|
+
(^|/)\.lock-wscript$
|
112
|
+
# mac os finder
|
113
|
+
(^|/)\.DS_Store$
|
114
|
+
|
115
|
+
### database_resetter
|
116
|
+
(^|/)tmp($|/)
|
117
|
+
(^|/).bundle($|/)
|
118
|
+
(^|/)pkg($|/)
|
@@ -0,0 +1,17 @@
|
|
1
|
+
Feature: Change environment
|
2
|
+
So that I don't obliterate my Cucumber database when running RSpec
|
3
|
+
As a wise developer who maintains separate testing environments
|
4
|
+
I want to specify the environment that gets reset
|
5
|
+
|
6
|
+
Scenario: Using environment "test"
|
7
|
+
Given a Rails-type project
|
8
|
+
And a fake test case for the "test" environment
|
9
|
+
When I run a test case
|
10
|
+
Then the database should be reset for the "test" environment
|
11
|
+
|
12
|
+
Scenario: Using environment "cucumber"
|
13
|
+
Given a Rails-type project
|
14
|
+
And a fake test case for the "cucumber" environment
|
15
|
+
When I run a test case
|
16
|
+
Then the database should be reset for the "cucumber" environment
|
17
|
+
|
@@ -0,0 +1,24 @@
|
|
1
|
+
Feature: Reset a database
|
2
|
+
In order to reduce time wasted manually running migrations
|
3
|
+
As a database-backed app developer
|
4
|
+
I want my databases rebuilt when I change the migrations
|
5
|
+
|
6
|
+
Scenario: Initial run
|
7
|
+
Given a Rails-type project
|
8
|
+
When I run a test case
|
9
|
+
Then the database should be reset
|
10
|
+
|
11
|
+
Scenario: Clean re-run
|
12
|
+
Given a Rails-type project
|
13
|
+
When I run a test case
|
14
|
+
And I run a test case again
|
15
|
+
Then the database should not be reset
|
16
|
+
|
17
|
+
Scenario: Dirty re-run
|
18
|
+
Given a Rails-type project
|
19
|
+
When I run a test case
|
20
|
+
And I touch a migration
|
21
|
+
And I run a test case again
|
22
|
+
Then the database should be reset
|
23
|
+
|
24
|
+
|
@@ -0,0 +1,24 @@
|
|
1
|
+
Feature: Different web frameworks
|
2
|
+
In order to enjoy the magic of an automatically-reset database on all my projects
|
3
|
+
As a promiscuous web framework fly-by-night
|
4
|
+
I want to reset databases in Rails, Merb, Sinatra and all that crazy shit
|
5
|
+
|
6
|
+
Scenario: Rails-type project
|
7
|
+
Given a Rails-type project
|
8
|
+
|
9
|
+
When I run a test case
|
10
|
+
Then the database should be reset
|
11
|
+
|
12
|
+
When I touch a migration
|
13
|
+
And I run a test case again
|
14
|
+
Then the database should be reset
|
15
|
+
|
16
|
+
Scenario: Merb-type project
|
17
|
+
Given a Merb-type project
|
18
|
+
|
19
|
+
When I run a test case
|
20
|
+
Then the database should be reset for the current Merb environment
|
21
|
+
|
22
|
+
When I touch a migration
|
23
|
+
And I run a test case again
|
24
|
+
Then the database should be reset for the current Merb environment
|
@@ -0,0 +1,19 @@
|
|
1
|
+
Feature: No migrations
|
2
|
+
So that I don't have to decipher an incomprehensible backtrace
|
3
|
+
As a bone idle and/or forgetful database-backed app developer
|
4
|
+
I want database_resetter to tell me when I forgot to make any migrations
|
5
|
+
|
6
|
+
# TODO Rails-specific issues need highlighting
|
7
|
+
|
8
|
+
Scenario: No migrations directory
|
9
|
+
Given an empty project called "empty-project"
|
10
|
+
When I run a test case
|
11
|
+
Then I should see "No migrations"
|
12
|
+
|
13
|
+
Scenario: No migrations in migration directory
|
14
|
+
Given an empty project called "empty-project"
|
15
|
+
And an empty Rails migration directory
|
16
|
+
When I run a test case
|
17
|
+
Then I should see "No migrations"
|
18
|
+
|
19
|
+
|
@@ -0,0 +1,125 @@
|
|
1
|
+
module DatabaseResetterHelpers
|
2
|
+
def create_project
|
3
|
+
create_dir(@project_name)
|
4
|
+
cd(@project_name)
|
5
|
+
create_fake_test_case
|
6
|
+
end
|
7
|
+
|
8
|
+
def create_fake_test_case(options = {})
|
9
|
+
options = {
|
10
|
+
:environment => "unimportant_env",
|
11
|
+
:migration_directory => "db/migrate",
|
12
|
+
:command_pattern => "rake db:reset RAILS_ENV=%ENV%"
|
13
|
+
}.merge(options)
|
14
|
+
|
15
|
+
create_file(
|
16
|
+
"fake_test_case.rb", <<-RUBY
|
17
|
+
require "rubygems"
|
18
|
+
require "database_resetter"
|
19
|
+
DatabaseResetter.new(
|
20
|
+
:environment => "#{options[:environment]}",
|
21
|
+
:migration_directory => "#{options[:migration_directory]}",
|
22
|
+
:command_pattern => "#{options[:command_pattern]}"
|
23
|
+
).reset_if_required
|
24
|
+
RUBY
|
25
|
+
)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
World(DatabaseResetterHelpers)
|
29
|
+
|
30
|
+
Given /^an empty project called "([^"]*)"$/ do |project_name|
|
31
|
+
@project_name = project_name
|
32
|
+
create_project
|
33
|
+
end
|
34
|
+
|
35
|
+
Given /^an empty Rails migration directory$/ do
|
36
|
+
create_dir("db/migrate")
|
37
|
+
end
|
38
|
+
|
39
|
+
Given /^a Rails-type project$/ do
|
40
|
+
@project_name = "rails-project"
|
41
|
+
create_project
|
42
|
+
|
43
|
+
@migration_dir = "db/migrate"
|
44
|
+
create_dir(@migration_dir)
|
45
|
+
create_file(
|
46
|
+
"#{@migration_dir}/001_first_migration.rb", <<-RUBY
|
47
|
+
# This is just a dummy migration file
|
48
|
+
RUBY
|
49
|
+
)
|
50
|
+
|
51
|
+
create_file(
|
52
|
+
"Rakefile", <<-RUBY
|
53
|
+
namespace :db do
|
54
|
+
task :reset do
|
55
|
+
puts "Invoked: rake db:reset RAILS_ENV=\#{ENV['RAILS_ENV']}"
|
56
|
+
end
|
57
|
+
end
|
58
|
+
RUBY
|
59
|
+
)
|
60
|
+
|
61
|
+
create_fake_test_case
|
62
|
+
end
|
63
|
+
|
64
|
+
Given /^a Merb-type project$/ do
|
65
|
+
@project_name = "merb-project"
|
66
|
+
create_project
|
67
|
+
|
68
|
+
@migration_dir = "schema/migrations"
|
69
|
+
create_dir(@migration_dir)
|
70
|
+
|
71
|
+
create_file(
|
72
|
+
"#{@migration_dir}/001_first_migration.rb", <<-RUBY
|
73
|
+
# This is just a dummy migration file
|
74
|
+
RUBY
|
75
|
+
)
|
76
|
+
|
77
|
+
create_file(
|
78
|
+
"Rakefile", <<-RUBY
|
79
|
+
namespace :db do
|
80
|
+
task :imaginary_merb_reset_task do
|
81
|
+
puts "Invoked: rake db:imaginary_merb_reset_task MERB_ENV=\#{ENV['MERB_ENV']}"
|
82
|
+
end
|
83
|
+
end
|
84
|
+
RUBY
|
85
|
+
)
|
86
|
+
|
87
|
+
create_fake_test_case(
|
88
|
+
:migration_directory => @migration_dir,
|
89
|
+
:command_pattern => "rake db:imaginary_merb_reset_task MERB_ENV=%ENV%",
|
90
|
+
:environment => "my_merb_env"
|
91
|
+
)
|
92
|
+
end
|
93
|
+
|
94
|
+
Given /^a fake test case for the "([^"]*)" environment$/ do |environment|
|
95
|
+
create_fake_test_case(:environment => environment)
|
96
|
+
end
|
97
|
+
|
98
|
+
Then /^the database should be reset$/ do
|
99
|
+
Then %'I should see "Invoked: rake db:reset"'
|
100
|
+
end
|
101
|
+
|
102
|
+
Then /^the database should not be reset$/ do
|
103
|
+
Then %'I should see "Skipping database reset"'
|
104
|
+
end
|
105
|
+
|
106
|
+
Then /^the database should be reset for the "([^"]*)" environment$/ do |environment|
|
107
|
+
Then %'I should see "Invoked: rake db:reset RAILS_ENV=#{environment}"'
|
108
|
+
end
|
109
|
+
|
110
|
+
Then /^the database should be reset for the current Merb environment$/ do
|
111
|
+
Then %'I should see "Invoked: rake db:imaginary_merb_reset_task MERB_ENV=my_merb_env"'
|
112
|
+
end
|
113
|
+
|
114
|
+
When /^I run a test case(?: again)?$/ do
|
115
|
+
run("ruby fake_test_case.rb")
|
116
|
+
end
|
117
|
+
|
118
|
+
When /^I touch a migration$/ do
|
119
|
+
sleep 1
|
120
|
+
create_file(
|
121
|
+
"#{@migration_dir}/001_first_migration.rb", <<-RUBY
|
122
|
+
# Modified migration file
|
123
|
+
RUBY
|
124
|
+
)
|
125
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
require 'time'
|
2
|
+
|
3
|
+
class DatabaseResetter
|
4
|
+
def initialize(options)
|
5
|
+
# NOTE There are no features/specs to prove the defaults are present
|
6
|
+
@environment = options[:environment] || ENV["RAILS_ENV"]
|
7
|
+
@command_pattern = options[:command_pattern] || "rake db:reset RAILS_ENV=%ENV%"
|
8
|
+
@files_to_watch = "#{options[:migration_directory] || "db/migrate"}/**/*.rb"
|
9
|
+
end
|
10
|
+
|
11
|
+
def reset_if_required
|
12
|
+
if migration_dir.empty?
|
13
|
+
puts "*** No migrations"
|
14
|
+
return
|
15
|
+
end
|
16
|
+
|
17
|
+
if migrations_changed_since_last_database_reset?
|
18
|
+
reset
|
19
|
+
else
|
20
|
+
puts "*** Skipping database reset (migrations not changed since last run)"
|
21
|
+
puts "*** Run `#{reset_command}` if necessary, or touch a migration"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def database_reset_time_file
|
28
|
+
"#{database_reset_dir}/#{@environment}"
|
29
|
+
end
|
30
|
+
|
31
|
+
def database_reset_dir
|
32
|
+
"log/database_resetter/#{`hostname`}"
|
33
|
+
end
|
34
|
+
|
35
|
+
def ensure_database_reset_dir
|
36
|
+
system "mkdir -p '#{database_reset_dir}'"
|
37
|
+
end
|
38
|
+
|
39
|
+
def reset
|
40
|
+
puts "*** Resetting #{@environment} database"
|
41
|
+
run_reset_command_or_raise
|
42
|
+
log_database_reset_time
|
43
|
+
puts "*** #{@environment.capitalize} database reset"
|
44
|
+
end
|
45
|
+
|
46
|
+
def migrations_changed_since_last_database_reset?
|
47
|
+
most_recent_migration_file_change_timestamp > last_database_reset_timestamp
|
48
|
+
end
|
49
|
+
|
50
|
+
def most_recent_migration_file_change_timestamp
|
51
|
+
migration_dir.map { |filename|
|
52
|
+
File.mtime(filename)
|
53
|
+
}.max
|
54
|
+
end
|
55
|
+
|
56
|
+
def last_database_reset_timestamp
|
57
|
+
File.open(database_reset_time_file) do |file|
|
58
|
+
Time.parse(file.readline)
|
59
|
+
end
|
60
|
+
rescue Errno::ENOENT
|
61
|
+
Time.at(0)
|
62
|
+
end
|
63
|
+
|
64
|
+
def log_database_reset_time
|
65
|
+
ensure_database_reset_dir
|
66
|
+
File.open(database_reset_time_file, "w") do |file|
|
67
|
+
file.puts(Time.new)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def run_reset_command_or_raise
|
72
|
+
raise "Command failed: #{reset_command}" unless run_reset_command
|
73
|
+
end
|
74
|
+
|
75
|
+
def run_reset_command
|
76
|
+
system(reset_command)
|
77
|
+
end
|
78
|
+
|
79
|
+
def reset_command
|
80
|
+
@command_pattern.gsub("%ENV%", @environment)
|
81
|
+
end
|
82
|
+
|
83
|
+
def migration_dir
|
84
|
+
Dir[@files_to_watch]
|
85
|
+
end
|
86
|
+
end
|
metadata
ADDED
@@ -0,0 +1,86 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: database_resetter
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 27
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 1
|
9
|
+
- 0
|
10
|
+
version: 0.1.0
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Ashley Moran
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2010-07-04 00:00:00 +01:00
|
19
|
+
default_executable:
|
20
|
+
dependencies: []
|
21
|
+
|
22
|
+
description:
|
23
|
+
email: ashley.moran@patchspace.co.uk
|
24
|
+
executables: []
|
25
|
+
|
26
|
+
extensions: []
|
27
|
+
|
28
|
+
extra_rdoc_files:
|
29
|
+
- README.markdown
|
30
|
+
files:
|
31
|
+
- Gemfile
|
32
|
+
- HISTORY.markdown
|
33
|
+
- LICENCE.markdown
|
34
|
+
- README.markdown
|
35
|
+
- Rakefile
|
36
|
+
- VERSION
|
37
|
+
- config/cucumber.yml
|
38
|
+
- config/darcs.boring
|
39
|
+
- lib/database_resetter.rb
|
40
|
+
- features/descriptions/change_environment.feature
|
41
|
+
- features/descriptions/database_resetter.feature
|
42
|
+
- features/descriptions/different_web_frameworks.feature
|
43
|
+
- features/descriptions/no_migrations.feature
|
44
|
+
- features/step_definitions/database_resetter_steps.rb
|
45
|
+
- features/support/env.rb
|
46
|
+
has_rdoc: true
|
47
|
+
homepage: https://patch-tag.com/repo/ashleymoran/database_resetter/
|
48
|
+
licenses: []
|
49
|
+
|
50
|
+
post_install_message:
|
51
|
+
rdoc_options:
|
52
|
+
- --charset=UTF-8
|
53
|
+
require_paths:
|
54
|
+
- lib
|
55
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
56
|
+
none: false
|
57
|
+
requirements:
|
58
|
+
- - ">="
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
hash: 3
|
61
|
+
segments:
|
62
|
+
- 0
|
63
|
+
version: "0"
|
64
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ">="
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
hash: 3
|
70
|
+
segments:
|
71
|
+
- 0
|
72
|
+
version: "0"
|
73
|
+
requirements: []
|
74
|
+
|
75
|
+
rubyforge_project:
|
76
|
+
rubygems_version: 1.3.7
|
77
|
+
signing_key:
|
78
|
+
specification_version: 3
|
79
|
+
summary: Automatically resets your database when migrations change
|
80
|
+
test_files:
|
81
|
+
- features/descriptions/change_environment.feature
|
82
|
+
- features/descriptions/database_resetter.feature
|
83
|
+
- features/descriptions/different_web_frameworks.feature
|
84
|
+
- features/descriptions/no_migrations.feature
|
85
|
+
- features/step_definitions/database_resetter_steps.rb
|
86
|
+
- features/support/env.rb
|