sequel_tools 0.1.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 +7 -0
- data/.gitignore +13 -0
- data/.rspec +3 -0
- data/.travis.yml +6 -0
- data/Gemfile +8 -0
- data/Gemfile.lock +39 -0
- data/LICENSE.txt +21 -0
- data/README.md +99 -0
- data/Rakefile +8 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/lib/sequel_tools.rb +42 -0
- data/lib/sequel_tools/actions/connect_db.rb +10 -0
- data/lib/sequel_tools/actions/create_db.rb +21 -0
- data/lib/sequel_tools/actions/down.rb +14 -0
- data/lib/sequel_tools/actions/drop_db.rb +22 -0
- data/lib/sequel_tools/actions/migrate.rb +19 -0
- data/lib/sequel_tools/actions/new_migration.rb +28 -0
- data/lib/sequel_tools/actions/redo.rb +14 -0
- data/lib/sequel_tools/actions/reset.rb +18 -0
- data/lib/sequel_tools/actions/rollback.rb +17 -0
- data/lib/sequel_tools/actions/schema_dump.rb +22 -0
- data/lib/sequel_tools/actions/schema_dump_postgres.rb +32 -0
- data/lib/sequel_tools/actions/schema_load.rb +23 -0
- data/lib/sequel_tools/actions/seed.rb +20 -0
- data/lib/sequel_tools/actions/setup.rb +20 -0
- data/lib/sequel_tools/actions/status.rb +26 -0
- data/lib/sequel_tools/actions/up.rb +14 -0
- data/lib/sequel_tools/actions/version.rb +13 -0
- data/lib/sequel_tools/actions_manager.rb +88 -0
- data/lib/sequel_tools/all_actions.rb +19 -0
- data/lib/sequel_tools/migration_utils.rb +52 -0
- data/lib/sequel_tools/pg_helper.rb +24 -0
- data/lib/sequel_tools/version.rb +5 -0
- data/scripts/ci/travis-build.sh +16 -0
- data/sequel_tools.gemspec +39 -0
- metadata +157 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: b25c97f4906a511718907a4eed3dd0961f546b81
|
4
|
+
data.tar.gz: 2d97d6cc1192d996208546842fcd1ba0090fd9b1
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 7be946fb5573e87ffb93a02ebc9b5b1dc497953117ad720df53c73ba028517ad63dfdf2c7a42b061e60aa188f1e0cb9705f6be63814dbedce3d05603a4c349fa
|
7
|
+
data.tar.gz: 837f5ad9998ec57cf5faf1750940831d9033c224638a2247f578bb5e05e0ce833e1344f50d633350d3afd9c81a4f88e1f4e32888875ea3e80af67b66df0ad3fc
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
sequel_tools (0.1.0)
|
5
|
+
sequel
|
6
|
+
|
7
|
+
GEM
|
8
|
+
remote: https://rubygems.org/
|
9
|
+
specs:
|
10
|
+
diff-lcs (1.3)
|
11
|
+
pg (0.21.0)
|
12
|
+
rake (12.3.0)
|
13
|
+
rspec (3.7.0)
|
14
|
+
rspec-core (~> 3.7.0)
|
15
|
+
rspec-expectations (~> 3.7.0)
|
16
|
+
rspec-mocks (~> 3.7.0)
|
17
|
+
rspec-core (3.7.0)
|
18
|
+
rspec-support (~> 3.7.0)
|
19
|
+
rspec-expectations (3.7.0)
|
20
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
21
|
+
rspec-support (~> 3.7.0)
|
22
|
+
rspec-mocks (3.7.0)
|
23
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
24
|
+
rspec-support (~> 3.7.0)
|
25
|
+
rspec-support (3.7.0)
|
26
|
+
sequel (5.3.0)
|
27
|
+
|
28
|
+
PLATFORMS
|
29
|
+
ruby
|
30
|
+
|
31
|
+
DEPENDENCIES
|
32
|
+
bundler
|
33
|
+
pg
|
34
|
+
rake
|
35
|
+
rspec
|
36
|
+
sequel_tools!
|
37
|
+
|
38
|
+
BUNDLED WITH
|
39
|
+
1.16.0
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2017 Rodrigo Rosenfeld Rosas
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,99 @@
|
|
1
|
+
# SequelTools
|
2
|
+
|
3
|
+
SequelTools brings some tooling around Sequel migrations and database management, providing tasks
|
4
|
+
to create, drop and migrate the database, plus dumping and restoring from the last migrated schema.
|
5
|
+
It can also display which migrations are applied and which ones are missing. It's highly
|
6
|
+
customizable and supports multiple databases or environments. It integrates well with Rake as well.
|
7
|
+
|
8
|
+
Currently only PostgreSQL is supported out-of-the-box for some tasks, but it should allow you to
|
9
|
+
specify the database vendor specific commands to support your vendor of choice without requiring
|
10
|
+
changes to SequelTools itself. Other vendors can be supported through additional gems or you may
|
11
|
+
want to submit pull requests for your preferred DB vendor if you prefer so that it would be
|
12
|
+
supported out-of-the-box by this gem.
|
13
|
+
|
14
|
+
The idea behind SequelTools is to create a collection of supported actions, which depend on the
|
15
|
+
database adapter/vendor. Those supported actions can then be translated to Rake tasks as a possible
|
16
|
+
interface.
|
17
|
+
|
18
|
+
## Installation
|
19
|
+
|
20
|
+
Add this line to your application's Gemfile:
|
21
|
+
|
22
|
+
```ruby
|
23
|
+
gem 'sequel_tools'
|
24
|
+
```
|
25
|
+
|
26
|
+
And then execute:
|
27
|
+
|
28
|
+
bundle
|
29
|
+
|
30
|
+
## Usage
|
31
|
+
|
32
|
+
Here's a sample Rakefile supporting migrate actions:
|
33
|
+
|
34
|
+
```ruby
|
35
|
+
require 'bundler/setup'
|
36
|
+
require 'sequel_tools'
|
37
|
+
|
38
|
+
base_config = SequelTools.base_config(
|
39
|
+
project_root: File.expand_path(__dir__),
|
40
|
+
dbadapter: 'postgres',
|
41
|
+
dbname: 'mydb',
|
42
|
+
username: 'myuser',
|
43
|
+
password: 'secret',
|
44
|
+
maintenancedb: 'postgres' # for tasks such as creating the database
|
45
|
+
)
|
46
|
+
|
47
|
+
namespace 'db' do
|
48
|
+
SequelTools.inject_rake_tasks base_config.merge(dump_schema_on_migrate: true), self
|
49
|
+
end
|
50
|
+
|
51
|
+
namespace 'dbtest' do
|
52
|
+
SequelTools.inject_rake_tasks base_config.merge(dbname: 'mydb_test'), self
|
53
|
+
end
|
54
|
+
```
|
55
|
+
|
56
|
+
Then you are able to run several tasks (`rake -T` will list all supported):
|
57
|
+
|
58
|
+
rake db:create
|
59
|
+
rake db:new_migration[migration_name]
|
60
|
+
rake db:migrate
|
61
|
+
rake dbtest:setup
|
62
|
+
|
63
|
+
## Development and running tests
|
64
|
+
|
65
|
+
The tests assume the database `sequel_tools_test_pw` exists and can be only accessed using a
|
66
|
+
username and password. It also assumes a valid user/passwd is `user_tools_user/secret`. The
|
67
|
+
database `sequel_tools_test` is also required to exist and it should be possible to access it
|
68
|
+
using the `trust` authentication method, without requiring a password. You may achieve that by
|
69
|
+
adding these lines to the start of your `pg_hba.conf`:
|
70
|
+
|
71
|
+
```
|
72
|
+
host sequel_tools_test_pw all 127.0.0.1/32 md5
|
73
|
+
host sequel_tools_test all 127.0.0.1/32 trust
|
74
|
+
```
|
75
|
+
|
76
|
+
Then feel free to run the tests:
|
77
|
+
|
78
|
+
bundle exec rspec
|
79
|
+
|
80
|
+
The default strategy is a safe one, which uses `Open3.capture3` to actually run
|
81
|
+
`bundle exec rake ...` whenever we want to test the Rake integration and we do that many times
|
82
|
+
in the tests. Running `bundle exec` is slow, so it adds a lot to the test suite total execution
|
83
|
+
time. Alternatively, although less robust, you may run the tests using a fork-rake approach,
|
84
|
+
which avoids calling `bundle exec` each time we want to run a Rake task. Just define
|
85
|
+
the `FORK_RAKE` environment variable:
|
86
|
+
|
87
|
+
FORK_RAKE=1 bundle exec rspec
|
88
|
+
|
89
|
+
In my environment this would complete the full suite in about half the time.
|
90
|
+
|
91
|
+
## Contributing
|
92
|
+
|
93
|
+
Bug reports and pull requests are welcome on GitHub at
|
94
|
+
[https://github.com/rosenfeld/sequel_tools](https://github.com/rosenfeld/sequel_tools).
|
95
|
+
|
96
|
+
## License
|
97
|
+
|
98
|
+
The gem is available as open source under the terms of the
|
99
|
+
[MIT License](https://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "sequel_tools"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start(__FILE__)
|
data/bin/setup
ADDED
data/lib/sequel_tools.rb
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
# frozen-string-literal: true
|
2
|
+
|
3
|
+
require 'sequel_tools/version'
|
4
|
+
|
5
|
+
module SequelTools
|
6
|
+
DEFAULT_CONFIG = {
|
7
|
+
project_root: nil,
|
8
|
+
pg_dump: 'pg_dump', # command used to run pg_dump
|
9
|
+
maintenancedb: 'postgres', # DB to connect to for creating/dropping databases
|
10
|
+
db_migrations_location: 'db/migrations',
|
11
|
+
schema_location: 'db/migrations/schema.sql',
|
12
|
+
seeds_location: 'db/seeds.rb',
|
13
|
+
dbname: nil,
|
14
|
+
dbhost: 'localhost',
|
15
|
+
dbadapter: 'postgres',
|
16
|
+
dbport: nil,
|
17
|
+
username: nil,
|
18
|
+
password: nil,
|
19
|
+
dump_schema_on_migrate: false,
|
20
|
+
} # unfrozen on purpose so that one might want to update the defaults
|
21
|
+
|
22
|
+
REQUIRED_KEYS = [ :project_root, :dbadapter, :dbname, :username ]
|
23
|
+
class MissingConfigError < StandardError; end
|
24
|
+
def self.base_config(extra_config = {})
|
25
|
+
config = DEFAULT_CONFIG.merge extra_config
|
26
|
+
REQUIRED_KEYS.each do |key|
|
27
|
+
raise MissingConfigError, "Expected value for #{key} config is missing" if config[key].nil?
|
28
|
+
end
|
29
|
+
[:db_migrations_location, :schema_location, :seeds_location].each do |k|
|
30
|
+
config[k] = File.expand_path config[k], config[:project_root]
|
31
|
+
end
|
32
|
+
config
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.inject_rake_tasks(config = {}, rake_context)
|
36
|
+
require_relative 'sequel_tools/actions_manager'
|
37
|
+
require_relative 'sequel_tools/all_actions'
|
38
|
+
actions_manager = ActionsManager.new config
|
39
|
+
actions_manager.load_all
|
40
|
+
actions_manager.export_as_rake_tasks rake_context
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
# frozen-string-literal: true
|
2
|
+
|
3
|
+
require 'sequel'
|
4
|
+
require_relative '../actions_manager'
|
5
|
+
|
6
|
+
SequelTools::ActionsManager::Action.register :connect_db, nil do |args, context|
|
7
|
+
next if context[:db]
|
8
|
+
context[:db] = Sequel.connect context[:uri_builder].call context[:config]
|
9
|
+
end
|
10
|
+
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen-string-literal: true
|
2
|
+
|
3
|
+
require 'sequel'
|
4
|
+
require_relative '../actions_manager'
|
5
|
+
|
6
|
+
class SequelTools::ActionsManager
|
7
|
+
Action.register :create, 'Create database' do |args, context|
|
8
|
+
begin
|
9
|
+
Action[:connect_db].run({}, context)
|
10
|
+
rescue
|
11
|
+
c = context[:config]
|
12
|
+
db = Sequel.connect context[:uri_builder].call(c, c[:maintenancedb])
|
13
|
+
db << "create database #{c[:dbname]}"
|
14
|
+
db.disconnect
|
15
|
+
else
|
16
|
+
puts 'Database already exists - aborting'
|
17
|
+
exit 1
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen-string-literal: true
|
2
|
+
|
3
|
+
require 'sequel'
|
4
|
+
require_relative '../actions_manager'
|
5
|
+
require_relative '../migration_utils'
|
6
|
+
|
7
|
+
class SequelTools::ActionsManager
|
8
|
+
desc = 'Run specified migration down if not already applied'
|
9
|
+
Action.register :down, desc, arg_names: [ :version ] do |args, context|
|
10
|
+
MigrationUtils.apply_migration context, args[:version], :down
|
11
|
+
Action[:schema_dump].run({}, context) if context[:config][:dump_schema_on_migrate]
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen-string-literal: true
|
2
|
+
|
3
|
+
require 'sequel'
|
4
|
+
require_relative '../actions_manager'
|
5
|
+
|
6
|
+
class SequelTools::ActionsManager
|
7
|
+
Action.register :drop, 'Drop database' do |args, context|
|
8
|
+
begin
|
9
|
+
Action[:connect_db].run({}, context)
|
10
|
+
rescue
|
11
|
+
puts 'Database does not exist - aborting.'
|
12
|
+
exit 1
|
13
|
+
else
|
14
|
+
context.delete(:db).disconnect
|
15
|
+
c = context[:config]
|
16
|
+
db = Sequel.connect context[:uri_builder].call(c, c[:maintenancedb])
|
17
|
+
db << "drop database #{c[:dbname]}"
|
18
|
+
db.disconnect
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen-string-literal: true
|
2
|
+
|
3
|
+
require 'sequel'
|
4
|
+
require_relative '../actions_manager'
|
5
|
+
|
6
|
+
class SequelTools::ActionsManager
|
7
|
+
desc = 'Migrate to specified version (last by default)'
|
8
|
+
Action.register :migrate, desc, arg_names: [ :version ] do |args, context|
|
9
|
+
Action[:connect_db].run({}, context)
|
10
|
+
db = context[:db]
|
11
|
+
config = context[:config]
|
12
|
+
Sequel.extension :migration unless Sequel.respond_to? :migration
|
13
|
+
options = {}
|
14
|
+
options[:target] = args[:version].to_i if args[:version]
|
15
|
+
Sequel::Migrator.run db, config[:db_migrations_location], options
|
16
|
+
Action[:schema_dump].run({}, context) if config[:dump_schema_on_migrate]
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen-string-literal: true
|
2
|
+
|
3
|
+
require_relative '../actions_manager'
|
4
|
+
|
5
|
+
class SequelTools::ActionsManager
|
6
|
+
desc = 'Creates a new migration'
|
7
|
+
Action.register :new_migration, desc, arg_names: [ :name ] do |args, context|
|
8
|
+
(puts 'Migration name is missing - aborting'; exit 1) unless name = args[:name]
|
9
|
+
require 'time'
|
10
|
+
migrations_path = context[:config][:db_migrations_location]
|
11
|
+
filename = "#{migrations_path}/#{Time.now.strftime '%Y%m%d%H%M%S'}_#{name}.rb"
|
12
|
+
File.write filename, <<~MIGRATIONS_TEMPLATE_END
|
13
|
+
# documentation available at http://sequel.jeremyevans.net/rdoc/files/doc/migration_rdoc.html
|
14
|
+
Sequel.migration do
|
15
|
+
change do
|
16
|
+
# create_table(:table_name) do
|
17
|
+
# primary_key :id
|
18
|
+
# String :name, null: false
|
19
|
+
# end
|
20
|
+
end
|
21
|
+
# or call up{} and down{}
|
22
|
+
end
|
23
|
+
MIGRATIONS_TEMPLATE_END
|
24
|
+
puts "The new migration file was created under #{filename.inspect}"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen-string-literal: true
|
2
|
+
|
3
|
+
require 'sequel'
|
4
|
+
require_relative '../actions_manager'
|
5
|
+
|
6
|
+
class SequelTools::ActionsManager
|
7
|
+
desc = 'Run specified migration down and up (redo)'
|
8
|
+
Action.register :redo, desc, arg_names: [ :version ] do |args, context|
|
9
|
+
Action[:down].run(args, context)
|
10
|
+
Action[:up].run(args, context)
|
11
|
+
Action[:schema_dump].run({}, context) if context[:config][:dump_schema_on_migrate]
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen-string-literal: true
|
2
|
+
|
3
|
+
require_relative '../actions_manager'
|
4
|
+
|
5
|
+
class SequelTools::ActionsManager
|
6
|
+
desc = 'Recreate database from scratch by running all migrations and seeds in a new database'
|
7
|
+
Action.register :reset, desc, arg_names: [ :version ] do |args, context|
|
8
|
+
begin
|
9
|
+
Action[:drop].run({}, context)
|
10
|
+
rescue
|
11
|
+
end
|
12
|
+
Action[:create].run({}, context)
|
13
|
+
Action[:migrate].run({}, context)
|
14
|
+
Action[:seed].run({}, context)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen-string-literal: true
|
2
|
+
|
3
|
+
require 'sequel'
|
4
|
+
require_relative '../actions_manager'
|
5
|
+
require_relative '../migration_utils'
|
6
|
+
|
7
|
+
class SequelTools::ActionsManager
|
8
|
+
Action.register :rollback, 'Rollback last applied migration' do |args, context|
|
9
|
+
unless last_found_migration = MigrationUtils.last_found_migration(context)
|
10
|
+
puts 'No existing migrations are applied - cannot rollback'
|
11
|
+
exit 1
|
12
|
+
end
|
13
|
+
MigrationUtils.apply_migration context, last_found_migration, :down
|
14
|
+
Action[:schema_dump].run({}, context) if context[:config][:dump_schema_on_migrate]
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen-string-literal: true
|
2
|
+
|
3
|
+
require_relative '../actions_manager'
|
4
|
+
|
5
|
+
class SequelTools::ActionsManager
|
6
|
+
Action.register :schema_dump, 'Store current db schema' do |args, context|
|
7
|
+
begin
|
8
|
+
Action[:connect_db].run({}, context)
|
9
|
+
rescue
|
10
|
+
puts 'Database does not exist - aborting.'
|
11
|
+
exit 1
|
12
|
+
else
|
13
|
+
c = context[:config]
|
14
|
+
unless action = Action[:"schema_dump_#{c[:dbadapter]}"]
|
15
|
+
puts "Dumping the db schema is not currently supported for #{c[:dbadapter]}. Aborting"
|
16
|
+
exit 1
|
17
|
+
end
|
18
|
+
action.run({}, context)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen-string-literal: true
|
2
|
+
|
3
|
+
require_relative '../actions_manager'
|
4
|
+
require_relative '../pg_helper'
|
5
|
+
|
6
|
+
class SequelTools::ActionsManager
|
7
|
+
Action.register :schema_dump_postgres, nil do |args, context|
|
8
|
+
c = context[:config]
|
9
|
+
pg_dump = c[:pg_dump]
|
10
|
+
schema_location = c[:schema_location]
|
11
|
+
|
12
|
+
stdout, stderr, success = PgHelper.run_pg_command c, "#{pg_dump} -s"
|
13
|
+
return unless success
|
14
|
+
content = stdout
|
15
|
+
if content =~ /schema_(migrations|info)/
|
16
|
+
stdout, stderr, success =
|
17
|
+
PgHelper.run_pg_command c, "#{pg_dump} -a -t schema_migrations -t schema_info --inserts"
|
18
|
+
unless success
|
19
|
+
puts 'failed to dump data for schema_migrations and schema_info. Aborting.'
|
20
|
+
exit 1
|
21
|
+
end
|
22
|
+
# to make it easier to see the git diffs and to reduce conflicts when working in separate
|
23
|
+
# branches, we use a separate line for each value in schema_migrations:
|
24
|
+
regex = /(?<=INSERT INTO schema_migrations VALUES \()(.*?)(?=\))/i
|
25
|
+
migration_data = stdout.sub(regex){ |m| "\n #{m.split(',').join(",\n ")}\n" }
|
26
|
+
content = [content, migration_data].join "\n\n"
|
27
|
+
end
|
28
|
+
require 'fileutils'
|
29
|
+
FileUtils.mkdir_p File.dirname schema_location
|
30
|
+
File.write schema_location, content
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen-string-literal: true
|
2
|
+
|
3
|
+
require_relative '../actions_manager'
|
4
|
+
|
5
|
+
class SequelTools::ActionsManager
|
6
|
+
description = 'Populates an empty database with previously dumped schema'
|
7
|
+
Action.register :schema_load, description do |args, context|
|
8
|
+
begin
|
9
|
+
Action[:connect_db].run({}, context)
|
10
|
+
rescue
|
11
|
+
puts 'Database does not exist - aborting.'
|
12
|
+
exit 1
|
13
|
+
else
|
14
|
+
schema_location = context[:config][:schema_location]
|
15
|
+
unless File.exist? schema_location
|
16
|
+
puts "Schema file '#{schema_location}' does not exist. Aborting."
|
17
|
+
exit 1
|
18
|
+
end
|
19
|
+
context[:db] << File.read(schema_location)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen-string-literal: true
|
2
|
+
|
3
|
+
require_relative '../actions_manager'
|
4
|
+
|
5
|
+
class SequelTools::ActionsManager
|
6
|
+
Action.register :seed, 'Load seeds from seeds.rb' do |args, context|
|
7
|
+
begin
|
8
|
+
Action[:connect_db].run({}, context)
|
9
|
+
rescue
|
10
|
+
puts 'Database does not exist - aborting.'
|
11
|
+
exit 1
|
12
|
+
else
|
13
|
+
if File.exist?(seeds_location = context[:config][:seeds_location])
|
14
|
+
::DB = context[:db]
|
15
|
+
load seeds_location
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen-string-literal: true
|
2
|
+
|
3
|
+
require_relative '../actions_manager'
|
4
|
+
|
5
|
+
class SequelTools::ActionsManager
|
6
|
+
description = 'Creates and populates a database with previously dumped schema and seeds'
|
7
|
+
Action.register :setup, description do |args, context|
|
8
|
+
begin
|
9
|
+
Action[:connect_db].run({}, context)
|
10
|
+
rescue
|
11
|
+
Action[:create].run({}, context)
|
12
|
+
Action[:schema_load].run({}, context)
|
13
|
+
Action[:seed].run({}, context)
|
14
|
+
else
|
15
|
+
puts 'Database already exists - aborting.'
|
16
|
+
exit 1
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen-string-literal: true
|
2
|
+
|
3
|
+
require 'sequel'
|
4
|
+
require_relative '../actions_manager'
|
5
|
+
require_relative '../migration_utils'
|
6
|
+
|
7
|
+
class SequelTools::ActionsManager
|
8
|
+
description = 'Show migrations status (applied and missing in migrations path vs unapplied)'
|
9
|
+
Action.register :status, description do |args, context|
|
10
|
+
unapplied, files_missing = MigrationUtils.migrations_differences context
|
11
|
+
path = context[:config][:db_migrations_location]
|
12
|
+
unless files_missing.empty?
|
13
|
+
puts "The following migrations were applied to the database but can't be found in #{path}:"
|
14
|
+
puts files_missing.map{|fn| " - #{fn}" }.join("\n")
|
15
|
+
puts
|
16
|
+
end
|
17
|
+
if unapplied.empty?
|
18
|
+
puts 'No pending migrations in the database' if files_missing.empty?
|
19
|
+
else
|
20
|
+
puts 'Unapplied migrations:'
|
21
|
+
puts unapplied.map{|fn| " - #{fn}" }.join("\n")
|
22
|
+
puts
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen-string-literal: true
|
2
|
+
|
3
|
+
require 'sequel'
|
4
|
+
require_relative '../actions_manager'
|
5
|
+
require_relative '../migration_utils'
|
6
|
+
|
7
|
+
class SequelTools::ActionsManager
|
8
|
+
desc = 'Run specified migration up if not already applied'
|
9
|
+
Action.register :up, desc, arg_names: [ :version ] do |args, context|
|
10
|
+
MigrationUtils.apply_migration context, args[:version], :up
|
11
|
+
Action[:schema_dump].run({}, context) if context[:config][:dump_schema_on_migrate]
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# frozen-string-literal: true
|
2
|
+
|
3
|
+
require 'sequel'
|
4
|
+
require_relative '../actions_manager'
|
5
|
+
require_relative '../migration_utils'
|
6
|
+
|
7
|
+
class SequelTools::ActionsManager
|
8
|
+
Action.register :version, 'Displays current version' do |args, context|
|
9
|
+
puts MigrationUtils.current_version(context) || 'No migrations applied'
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
|
@@ -0,0 +1,88 @@
|
|
1
|
+
# frozen-string-literal: true
|
2
|
+
|
3
|
+
module SequelTools
|
4
|
+
class ActionsManager
|
5
|
+
attr_reader :actions, :context
|
6
|
+
|
7
|
+
URI_BUILDER = ->(config, dbname = config[:dbname]) do
|
8
|
+
c = config
|
9
|
+
uri_parts = [ "#{c[:dbadapter]}://" ]
|
10
|
+
if user = c[:username]
|
11
|
+
uri_parts << user
|
12
|
+
uri_parts << ':' << c[:password] if c[:password]
|
13
|
+
uri_parts << '@'
|
14
|
+
end
|
15
|
+
uri_parts << c[:dbhost]
|
16
|
+
uri_parts << ':' << c[:dbport] if c[:dbport]
|
17
|
+
uri_parts << '/' << dbname
|
18
|
+
uri_parts.join('')
|
19
|
+
end
|
20
|
+
|
21
|
+
def initialize(config)
|
22
|
+
@actions = []
|
23
|
+
@context = { config: config, uri_builder: URI_BUILDER }
|
24
|
+
end
|
25
|
+
|
26
|
+
def load_all
|
27
|
+
@actions.concat Action.registered
|
28
|
+
end
|
29
|
+
|
30
|
+
def export_as_rake_tasks(rake_context)
|
31
|
+
actions.each do |action|
|
32
|
+
ctx = context
|
33
|
+
rake_context.instance_eval do
|
34
|
+
desc action.description unless action.description.nil?
|
35
|
+
task action.name, action.arg_names do |t, args|
|
36
|
+
action.run args, ctx
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
class Action
|
43
|
+
attr_reader :name, :description, :arg_names, :block
|
44
|
+
|
45
|
+
def initialize(name, description, arg_names: [], &block)
|
46
|
+
@name, @description, @arg_names, @block = name, description, arg_names, block
|
47
|
+
end
|
48
|
+
|
49
|
+
def run(args, context)
|
50
|
+
@block.call args, context
|
51
|
+
end
|
52
|
+
|
53
|
+
@@registered = []
|
54
|
+
@@registered_by_name = {}
|
55
|
+
class AlreadyRegisteredAction < StandardError; end
|
56
|
+
def self.register(name, description, arg_names: [], &block)
|
57
|
+
if @@registered_by_name[name]
|
58
|
+
raise AlreadyRegisteredAction, "Attempt to register #{name} twice"
|
59
|
+
end
|
60
|
+
@@registered <<
|
61
|
+
(@@registered_by_name[name] = Action.new name, description, arg_names: arg_names, &block)
|
62
|
+
end
|
63
|
+
|
64
|
+
def self.registered
|
65
|
+
@@registered
|
66
|
+
end
|
67
|
+
|
68
|
+
def self.[](name)
|
69
|
+
@@registered_by_name[name]
|
70
|
+
end
|
71
|
+
|
72
|
+
def self.unregister(name)
|
73
|
+
return unless action = @@registered_by_name.delete(name)
|
74
|
+
@@registered.delete action
|
75
|
+
action
|
76
|
+
end
|
77
|
+
|
78
|
+
def self.replace(name, description, arg_names: [], &block)
|
79
|
+
unregister name
|
80
|
+
register name, description, arg_names: arg_names, &block
|
81
|
+
end
|
82
|
+
|
83
|
+
def self.register_action(action)
|
84
|
+
register action.name, action.description, arg_names: action.arg_names, &action.block
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen-string-literal: true
|
2
|
+
|
3
|
+
require_relative 'actions/connect_db'
|
4
|
+
require_relative 'actions/create_db'
|
5
|
+
require_relative 'actions/drop_db'
|
6
|
+
require_relative 'actions/schema_dump_postgres'
|
7
|
+
require_relative 'actions/schema_dump'
|
8
|
+
require_relative 'actions/schema_load'
|
9
|
+
require_relative 'actions/new_migration'
|
10
|
+
require_relative 'actions/migrate'
|
11
|
+
require_relative 'actions/reset'
|
12
|
+
require_relative 'actions/setup'
|
13
|
+
require_relative 'actions/seed'
|
14
|
+
require_relative 'actions/up'
|
15
|
+
require_relative 'actions/down'
|
16
|
+
require_relative 'actions/redo'
|
17
|
+
require_relative 'actions/version'
|
18
|
+
require_relative 'actions/rollback'
|
19
|
+
require_relative 'actions/status'
|
@@ -0,0 +1,52 @@
|
|
1
|
+
# frozen-string-literal: true
|
2
|
+
|
3
|
+
require_relative 'actions_manager'
|
4
|
+
require 'sequel'
|
5
|
+
|
6
|
+
class MigrationUtils
|
7
|
+
def self.apply_migration(context, version, direction)
|
8
|
+
( puts 'migration version is missing - aborting.'; exit 1 ) if version.nil?
|
9
|
+
filename = "#{File.basename version, '.rb'}.rb"
|
10
|
+
migrator = find_migrator context, direction
|
11
|
+
migrator.migration_tuples.delete_if{|(m, fn, dir)| fn != filename }
|
12
|
+
unless (size = migrator.migration_tuples.size) == 1
|
13
|
+
puts "Expected a single unapplied migration for #{filename} but found #{size}. Aborting."
|
14
|
+
exit 1
|
15
|
+
end
|
16
|
+
migrator.run
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.find_migrator(context, direction = :up)
|
20
|
+
Sequel.extension :migration unless Sequel.respond_to? :migration
|
21
|
+
SequelTools::ActionsManager::Action[:connect_db].run({}, context) unless context[:db]
|
22
|
+
options = { allow_missing_migration_files: true }
|
23
|
+
options[:target] = 0 if direction == :down
|
24
|
+
config = context[:config]
|
25
|
+
Sequel::Migrator.migrator_class(config[:db_migrations_location]).
|
26
|
+
new(context[:db], config[:db_migrations_location], options)
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.current_version(context)
|
30
|
+
migrator = find_migrator(context)
|
31
|
+
migrator.ds.order(Sequel.desc(migrator.column)).get migrator.column
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.last_found_migration(context)
|
35
|
+
migrations_path = context[:config][:db_migrations_location]
|
36
|
+
migrator = find_migrator(context)
|
37
|
+
migrator.ds.order(Sequel.desc(migrator.column)).select_map(migrator.column).find do |fn|
|
38
|
+
File.exist?("#{migrations_path}/#{fn}")
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.migrations_differences(context)
|
43
|
+
config = context[:config]
|
44
|
+
migrations_path = config[:db_migrations_location]
|
45
|
+
existing = Dir["#{migrations_path}/*.rb"].map{|fn| File.basename fn }.sort
|
46
|
+
migrator = find_migrator context
|
47
|
+
migrated = migrator.ds.select_order_map(migrator.column)
|
48
|
+
unapplied = existing - migrated
|
49
|
+
files_missing = migrated - existing
|
50
|
+
[ unapplied, files_missing ]
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen-string-literal: true
|
2
|
+
|
3
|
+
class PgHelper
|
4
|
+
def self.run_pg_command(config, cmd, connect_database: nil)
|
5
|
+
require 'open3'
|
6
|
+
require 'tempfile'
|
7
|
+
Tempfile.open 'pgpass' do |file|
|
8
|
+
c = config
|
9
|
+
file.chmod 0600
|
10
|
+
file.write "#{c[:dbhost]}:#{c[:dbport]}:#{c[:dbname]}:#{c[:username]}:#{c[:password]}"
|
11
|
+
file.close
|
12
|
+
env = {
|
13
|
+
'PGDATABASE' => connect_database || c[:dbname],
|
14
|
+
'PGHOST' => c[:dbhost],
|
15
|
+
'PGPORT' => c[:dbport].to_s,
|
16
|
+
'PGUSER' => c[:username],
|
17
|
+
'PGPASSFILE' => file.path
|
18
|
+
}
|
19
|
+
stdout, stderr, status = Open3.capture3 env, cmd
|
20
|
+
puts "#{cmd} failed: #{[stderr, stdout].join "\n\n"}" if status != 0
|
21
|
+
[ stdout, stderr, status == 0 ]
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
#!/bin/bash
|
2
|
+
|
3
|
+
# This script enable PG 9.6, creates the sequel_tools_test_pw database, which can be only
|
4
|
+
# accessed using a password through localhost, and the sequel_tools_test database which can be
|
5
|
+
# accessed using the trust method. It also creates the sequel_tools_user user with password
|
6
|
+
# 'secret'. This way we can test accessing the database both using a username and password or
|
7
|
+
# other methods defined by pg_hba.conf, such as trust, which doesn't require a password.
|
8
|
+
|
9
|
+
sudo /etc/init.d/postgresql stop
|
10
|
+
PGVERSION=9.6
|
11
|
+
PGHBA=/etc/postgresql/$PGVERSION/main/pg_hba.conf
|
12
|
+
sudo bash -c "sed -i '1i host sequel_tools_test_pw all 127.0.0.1/32 md5' $PGHBA"
|
13
|
+
sudo /etc/init.d/postgresql start $PGVERSION
|
14
|
+
psql -c "create user sequel_tools_user superuser password 'secret'" postgres
|
15
|
+
psql -U sequel_tools_user -c "create database sequel_tools_test" postgres
|
16
|
+
psql -U sequel_tools_user -c "create database sequel_tools_test_pw" postgres
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen-string-literal: true
|
2
|
+
|
3
|
+
lib = File.expand_path('lib', __dir__)
|
4
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
5
|
+
require 'sequel_tools/version'
|
6
|
+
|
7
|
+
Gem::Specification.new do |spec|
|
8
|
+
spec.name = 'sequel_tools'
|
9
|
+
spec.version = SequelTools::VERSION
|
10
|
+
spec.authors = ['Rodrigo Rosenfeld Rosas']
|
11
|
+
spec.email = ['rr.rosas@gmail.com']
|
12
|
+
|
13
|
+
spec.summary = %q{Add Rake tasks to manage Sequel migrations}
|
14
|
+
spec.description = <<~DESCRIPTION_END
|
15
|
+
Offer tooling for common database operations, such as running Sequel migrations, store and
|
16
|
+
load from the database schema, rollback, redo some migration, rerun all migrations, display
|
17
|
+
applied and missing migrations. It allows integration with Rake, while being lazily evaluated
|
18
|
+
to not slow down other Rake tasks. It's also configurable in order to support more actions
|
19
|
+
and database vendors. Some tasks are currently implemented for PostgreSQL only for the time
|
20
|
+
being out of the box. It should be possible to complement this gem with another one to
|
21
|
+
support other database vendors, while taking advantage of the build blocks provided by this
|
22
|
+
tool set.
|
23
|
+
DESCRIPTION_END
|
24
|
+
spec.homepage = 'https://github.com/rosenfeld/sequel_tools'
|
25
|
+
spec.license = 'MIT'
|
26
|
+
|
27
|
+
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
28
|
+
f.match(%r{^spec/})
|
29
|
+
end
|
30
|
+
#spec.bindir = 'exe'
|
31
|
+
#spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
32
|
+
spec.require_paths = ['lib']
|
33
|
+
|
34
|
+
spec.add_runtime_dependency 'sequel'
|
35
|
+
spec.add_development_dependency 'pg'
|
36
|
+
spec.add_development_dependency 'bundler'
|
37
|
+
spec.add_development_dependency 'rake'
|
38
|
+
spec.add_development_dependency 'rspec'
|
39
|
+
end
|
metadata
ADDED
@@ -0,0 +1,157 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: sequel_tools
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Rodrigo Rosenfeld Rosas
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2017-12-15 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: sequel
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: pg
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: bundler
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rake
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rspec
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
description: |
|
84
|
+
Offer tooling for common database operations, such as running Sequel migrations, store and
|
85
|
+
load from the database schema, rollback, redo some migration, rerun all migrations, display
|
86
|
+
applied and missing migrations. It allows integration with Rake, while being lazily evaluated
|
87
|
+
to not slow down other Rake tasks. It's also configurable in order to support more actions
|
88
|
+
and database vendors. Some tasks are currently implemented for PostgreSQL only for the time
|
89
|
+
being out of the box. It should be possible to complement this gem with another one to
|
90
|
+
support other database vendors, while taking advantage of the build blocks provided by this
|
91
|
+
tool set.
|
92
|
+
email:
|
93
|
+
- rr.rosas@gmail.com
|
94
|
+
executables: []
|
95
|
+
extensions: []
|
96
|
+
extra_rdoc_files: []
|
97
|
+
files:
|
98
|
+
- ".gitignore"
|
99
|
+
- ".rspec"
|
100
|
+
- ".travis.yml"
|
101
|
+
- Gemfile
|
102
|
+
- Gemfile.lock
|
103
|
+
- LICENSE.txt
|
104
|
+
- README.md
|
105
|
+
- Rakefile
|
106
|
+
- bin/console
|
107
|
+
- bin/setup
|
108
|
+
- lib/sequel_tools.rb
|
109
|
+
- lib/sequel_tools/actions/connect_db.rb
|
110
|
+
- lib/sequel_tools/actions/create_db.rb
|
111
|
+
- lib/sequel_tools/actions/down.rb
|
112
|
+
- lib/sequel_tools/actions/drop_db.rb
|
113
|
+
- lib/sequel_tools/actions/migrate.rb
|
114
|
+
- lib/sequel_tools/actions/new_migration.rb
|
115
|
+
- lib/sequel_tools/actions/redo.rb
|
116
|
+
- lib/sequel_tools/actions/reset.rb
|
117
|
+
- lib/sequel_tools/actions/rollback.rb
|
118
|
+
- lib/sequel_tools/actions/schema_dump.rb
|
119
|
+
- lib/sequel_tools/actions/schema_dump_postgres.rb
|
120
|
+
- lib/sequel_tools/actions/schema_load.rb
|
121
|
+
- lib/sequel_tools/actions/seed.rb
|
122
|
+
- lib/sequel_tools/actions/setup.rb
|
123
|
+
- lib/sequel_tools/actions/status.rb
|
124
|
+
- lib/sequel_tools/actions/up.rb
|
125
|
+
- lib/sequel_tools/actions/version.rb
|
126
|
+
- lib/sequel_tools/actions_manager.rb
|
127
|
+
- lib/sequel_tools/all_actions.rb
|
128
|
+
- lib/sequel_tools/migration_utils.rb
|
129
|
+
- lib/sequel_tools/pg_helper.rb
|
130
|
+
- lib/sequel_tools/version.rb
|
131
|
+
- scripts/ci/travis-build.sh
|
132
|
+
- sequel_tools.gemspec
|
133
|
+
homepage: https://github.com/rosenfeld/sequel_tools
|
134
|
+
licenses:
|
135
|
+
- MIT
|
136
|
+
metadata: {}
|
137
|
+
post_install_message:
|
138
|
+
rdoc_options: []
|
139
|
+
require_paths:
|
140
|
+
- lib
|
141
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - ">="
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '0'
|
146
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
147
|
+
requirements:
|
148
|
+
- - ">="
|
149
|
+
- !ruby/object:Gem::Version
|
150
|
+
version: '0'
|
151
|
+
requirements: []
|
152
|
+
rubyforge_project:
|
153
|
+
rubygems_version: 2.6.13
|
154
|
+
signing_key:
|
155
|
+
specification_version: 4
|
156
|
+
summary: Add Rake tasks to manage Sequel migrations
|
157
|
+
test_files: []
|