miguel 0.1.0.pre1 → 0.1.0.pre2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.travis.gemfile +9 -0
- data/.travis.yml +16 -0
- data/README.md +191 -0
- data/TODO +0 -1
- data/examples/db.yml +21 -0
- data/examples/schema.rb +133 -0
- data/miguel.gemspec +3 -2
- data/test/test_dumper.rb +7 -7
- metadata +9 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6cc20233657ee51f12faa39ae0c81c55184b09cb
|
4
|
+
data.tar.gz: 983d7e268d3cd5f9448b128b56f84f5a2f64cdea
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 61288b386f01bf54e2fedda5f0988e70ab0aaf3eb2133279b43ebc69f277a7cff39c57170eb92c5209fd418dd0a1613ef9ef43a87d75f2d6112ebbcfa96c8b66
|
7
|
+
data.tar.gz: 43f256c47f62d61d58f2031d5ec0cbcf6c8d1ce89c0e583e272c7701d9e618e8d51590010412ba4fb37bfca506c49e08f625ac15004ae6541f58f2d7d2107bfe
|
data/.gitignore
CHANGED
data/.travis.gemfile
ADDED
data/.travis.yml
ADDED
data/README.md
ADDED
@@ -0,0 +1,191 @@
|
|
1
|
+
# Miguel
|
2
|
+
|
3
|
+
[![Gem Version](https://img.shields.io/gem/v/miguel.svg)](http://rubygems.org/gems/miguel) [![Build Status](https://img.shields.io/travis/raxoft/miguel.svg?branch=master)](http://travis-ci.org/raxoft/miguel) [![Dependency Status](https://img.shields.io/gemnasium/raxoft/miguel.svg)](https://gemnasium.com/raxoft/miguel) [![Code Climate](https://img.shields.io/codeclimate/github/raxoft/miguel.svg)](https://codeclimate.com/github/raxoft/miguel) [![Coverage](https://img.shields.io/codeclimate/coverage/github/raxoft/miguel.svg)](https://codeclimate.com/github/raxoft/miguel)
|
4
|
+
|
5
|
+
Miguel is a tool for sane management of database schemas. It aims to help with these goals:
|
6
|
+
|
7
|
+
* Have just one up-to-date description of the desired database schema using a concise DSL.
|
8
|
+
* Apply that schema to the database anytime, no matter how either may have diverged.
|
9
|
+
* Adjust and repeat as often as needed.
|
10
|
+
|
11
|
+
To achieve this, it provides the following features:
|
12
|
+
|
13
|
+
* [Sequel](http://sequel.jeremyevans.net/)-like DSL for schema description with some enhancements.
|
14
|
+
* Load schema from given description file or from given database.
|
15
|
+
* Show changes necessary to turn one schema into another.
|
16
|
+
* Render those changes as Sequel's change or up/down migrations.
|
17
|
+
* Alternatively apply those changes directly to the database.
|
18
|
+
|
19
|
+
## Describing the schema
|
20
|
+
|
21
|
+
The schema is described using a DSL similar to Sequel's
|
22
|
+
[standard schema syntax](http://sequel.jeremyevans.net/rdoc/files/doc/schema_modification_rdoc.html).
|
23
|
+
It looks like this:
|
24
|
+
|
25
|
+
``` ruby
|
26
|
+
# Example schema for Miguel.
|
27
|
+
Miguel::Schema.define do
|
28
|
+
|
29
|
+
# The user, the core of every web site.
|
30
|
+
|
31
|
+
table :users do
|
32
|
+
primary_key :id
|
33
|
+
|
34
|
+
# The login id, usually user email address.
|
35
|
+
String :login
|
36
|
+
# The encrypted password.
|
37
|
+
String :password
|
38
|
+
|
39
|
+
# First name(s).
|
40
|
+
String :first_name
|
41
|
+
# Last name(s).
|
42
|
+
String :last_name
|
43
|
+
|
44
|
+
# Arbitrary JSON encoded info.
|
45
|
+
Text? :info
|
46
|
+
|
47
|
+
timestamps
|
48
|
+
|
49
|
+
unique :login
|
50
|
+
index :first_name
|
51
|
+
index :last_name
|
52
|
+
index :create_time
|
53
|
+
end
|
54
|
+
|
55
|
+
# User's emails, as every user can have multiple emails.
|
56
|
+
|
57
|
+
table :user_emails do
|
58
|
+
primary_key :id
|
59
|
+
|
60
|
+
# The email address itself.
|
61
|
+
String :email
|
62
|
+
# To which user does the email belong.
|
63
|
+
foreign_key :user_id, :users
|
64
|
+
|
65
|
+
# Flag set when this email is verified.
|
66
|
+
False :verified
|
67
|
+
# Flag set when this email is marked as their primary email by the user.
|
68
|
+
False :primary
|
69
|
+
|
70
|
+
timestamps
|
71
|
+
|
72
|
+
unique :email
|
73
|
+
index :user_id
|
74
|
+
index :create_time
|
75
|
+
end
|
76
|
+
|
77
|
+
# User's profile, collecting various info about the user.
|
78
|
+
|
79
|
+
table :user_profiles do
|
80
|
+
primary_key :user_id
|
81
|
+
foreign_key [:user_id], :users
|
82
|
+
|
83
|
+
String? :company
|
84
|
+
String? :street
|
85
|
+
String? :city
|
86
|
+
String? :state
|
87
|
+
String? :country
|
88
|
+
String? :zip
|
89
|
+
String? :phone
|
90
|
+
String? :fax
|
91
|
+
String? :url
|
92
|
+
|
93
|
+
index :country
|
94
|
+
index :state
|
95
|
+
end
|
96
|
+
|
97
|
+
# User's followers.
|
98
|
+
|
99
|
+
join_table :user_id, :users, :follower_id, :users, :user_followers
|
100
|
+
|
101
|
+
end
|
102
|
+
```
|
103
|
+
|
104
|
+
One enhancement is that it allows you to define `NULL` columns simply by adding `?` to the type name.
|
105
|
+
Anything else is implicitly `NOT NULL`, which is a really wise default.
|
106
|
+
|
107
|
+
Another enhancement is that it allows you to set defaults and
|
108
|
+
define custom shortcuts for types which you use frequently.
|
109
|
+
See documentation of the `set_defaults` method for details.
|
110
|
+
The preset defaults are like this:
|
111
|
+
|
112
|
+
``` ruby
|
113
|
+
set_defaults :global, :null => false
|
114
|
+
set_defaults :primary_key, :type => :integer, :unsigned => true
|
115
|
+
set_defaults :foreign_key, :key => :id, :type => :integer, :unsigned => true
|
116
|
+
set_defaults :unique, :index, :unique => true
|
117
|
+
set_defaults :Bool, :TrueClass
|
118
|
+
set_defaults :True, :TrueClass, :default => true
|
119
|
+
set_defaults :False, :TrueClass, :default => false
|
120
|
+
set_defaults :Signed, :integer, :unsigned => false
|
121
|
+
set_defaults :Unsigned, :integer, :unsigned => true
|
122
|
+
set_defaults :Text, :String, :text => true
|
123
|
+
set_defaults :Time, :timestamp, :default => 0
|
124
|
+
set_defaults :Time?, :timestamp, :default => nil
|
125
|
+
```
|
126
|
+
|
127
|
+
Finally, the `timestamp` helper can be used to create the
|
128
|
+
`create_time` and `update_time` timestamps for you.
|
129
|
+
|
130
|
+
## Using the command
|
131
|
+
|
132
|
+
Using the command should be pretty straightforward.
|
133
|
+
Try `miguel -h` and follow the examples.
|
134
|
+
You can basically:
|
135
|
+
|
136
|
+
* `show` - show schema loaded from given `.rb` file or from given database.
|
137
|
+
* `dump` - dump migration which creates such schema.
|
138
|
+
* `down` - dump migration which reverses given schema entirely.
|
139
|
+
* `diff` - dump migration for migrating from one schema to another.
|
140
|
+
* `apply` - apply given schema to given database.
|
141
|
+
* `clear` - entirely wipe out schema of given database.
|
142
|
+
|
143
|
+
You don't have to worry about changing things accidentally,
|
144
|
+
the command will always ask for a confirmation before changing anything in the database
|
145
|
+
(unless you use the `--force` option).
|
146
|
+
|
147
|
+
Databases can be specified either by their Sequel URL like
|
148
|
+
`mysql2://user:password@localhost/main`,
|
149
|
+
or by the common database `.yml` config file:
|
150
|
+
|
151
|
+
``` yaml
|
152
|
+
adapter: mysql2
|
153
|
+
user: jim
|
154
|
+
password: sup3rsecr3t
|
155
|
+
host: localhost
|
156
|
+
database: main
|
157
|
+
encoding: utf8
|
158
|
+
```
|
159
|
+
|
160
|
+
Note that you can use the `--env` option to specify an environment other than `development`
|
161
|
+
if your `.yml` contains configs for multiple environments.
|
162
|
+
|
163
|
+
Use the `--migration <format>` option to choose how you want the migration displayed.
|
164
|
+
The `bare` format (the default) shows just the changes themselves,
|
165
|
+
the `change` format creates the one-way Sequel's change migration,
|
166
|
+
relying on Sequel's ability to reverse it,
|
167
|
+
while
|
168
|
+
the `full` format creates the two-way Sequel's up/down migration.
|
169
|
+
|
170
|
+
It's up to you if you will use `diff` each time to create the migration files for you,
|
171
|
+
amend them if needed,
|
172
|
+
and then let the `sequel` command use them normally,
|
173
|
+
or if you will just `apply` the schema directly
|
174
|
+
and rely on your VCS to keep its previous versions for you,
|
175
|
+
leaving dozens of piecewise migration files finally behind.
|
176
|
+
|
177
|
+
## Limitations
|
178
|
+
|
179
|
+
The type support is geared towards the MySQL, especially the timestamp types.
|
180
|
+
Generic types should work with any database, but your mileage may vary.
|
181
|
+
|
182
|
+
It is currently not possible to describe renaming of columns.
|
183
|
+
If you need that,
|
184
|
+
simply rename the columns directly in the database or by using standard Sequel migration,
|
185
|
+
and adjust the schema description accordingly.
|
186
|
+
|
187
|
+
## Credits
|
188
|
+
|
189
|
+
Copyright © 2015 Patrik Rak
|
190
|
+
|
191
|
+
Miguel is released under the MIT license.
|
data/examples/db.yml
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
# Example database configuration.
|
2
|
+
|
3
|
+
# Development database.
|
4
|
+
:development:
|
5
|
+
:adapter: mysql2
|
6
|
+
:user: dev
|
7
|
+
:password: hax0rz
|
8
|
+
:host: localhost
|
9
|
+
:database: test
|
10
|
+
:encoding: utf8
|
11
|
+
|
12
|
+
# Production database.
|
13
|
+
:production:
|
14
|
+
:adapter: mysql2
|
15
|
+
:user: web
|
16
|
+
:password: aGhiTheig6iex6shieMohz5orsomethinglikethat
|
17
|
+
:host: localhost
|
18
|
+
:database: main
|
19
|
+
:encoding: utf8
|
20
|
+
|
21
|
+
# EOF #
|
data/examples/schema.rb
ADDED
@@ -0,0 +1,133 @@
|
|
1
|
+
# Example schema for Miguel.
|
2
|
+
#
|
3
|
+
# Few words on indexes/indices, applying to Sequel migrations in general:
|
4
|
+
#
|
5
|
+
# Create explicit indexes even for foreign keys, to make them named the Sequel way.
|
6
|
+
# This also prevents MySQL from using combined index starting with that column for the foreign key.
|
7
|
+
# Such combined index couldn't be dropped later because of the foreign key constraint,
|
8
|
+
# at least until you would create an explicit one for that single column.
|
9
|
+
#
|
10
|
+
# Do not create overly complicated indexes before performance proves you really need them.
|
11
|
+
# Remember that every index increases insertion time considerably and takes space,
|
12
|
+
# so you should always start only with the basic indexes for the fields you need.
|
13
|
+
|
14
|
+
Miguel::Schema.define do
|
15
|
+
|
16
|
+
set_standard_defaults
|
17
|
+
|
18
|
+
# The user, the core of every web site.
|
19
|
+
|
20
|
+
table :users do
|
21
|
+
primary_key :id
|
22
|
+
|
23
|
+
# The login id, usually user email address.
|
24
|
+
String :login
|
25
|
+
# The encrypted password.
|
26
|
+
String :password
|
27
|
+
|
28
|
+
# Random bytes associated with this user, used in hashing and encrypting user specific things.
|
29
|
+
String :secret
|
30
|
+
|
31
|
+
# First name(s).
|
32
|
+
String :first_name
|
33
|
+
# Last name(s).
|
34
|
+
String :last_name
|
35
|
+
|
36
|
+
# String describing which permissions and what access rights the user has, separated by comma.
|
37
|
+
Text :permissions
|
38
|
+
|
39
|
+
# Arbitrary JSON encoded info.
|
40
|
+
Text? :info
|
41
|
+
|
42
|
+
timestamps
|
43
|
+
|
44
|
+
unique :login
|
45
|
+
index :first_name
|
46
|
+
index :last_name
|
47
|
+
index :create_time
|
48
|
+
end
|
49
|
+
|
50
|
+
# User's emails, as every user can have multiple emails.
|
51
|
+
|
52
|
+
table :user_emails do
|
53
|
+
primary_key :id
|
54
|
+
|
55
|
+
# The email address itself.
|
56
|
+
String :email
|
57
|
+
# To which user does the email belong.
|
58
|
+
foreign_key :user_id, :users
|
59
|
+
|
60
|
+
# Flag set when this email is verified.
|
61
|
+
False :verified
|
62
|
+
# Flag set when this email is marked as their primary email by the user.
|
63
|
+
False :primary
|
64
|
+
|
65
|
+
timestamps
|
66
|
+
|
67
|
+
unique :email
|
68
|
+
index :user_id
|
69
|
+
index :create_time
|
70
|
+
end
|
71
|
+
|
72
|
+
# User's profile, collecting various info about the user.
|
73
|
+
|
74
|
+
table :user_profiles do
|
75
|
+
primary_key :user_id
|
76
|
+
foreign_key [:user_id], :users
|
77
|
+
|
78
|
+
String? :company
|
79
|
+
String? :street
|
80
|
+
String? :city
|
81
|
+
String? :state
|
82
|
+
String? :country
|
83
|
+
String? :zip
|
84
|
+
String? :phone
|
85
|
+
String? :fax
|
86
|
+
String? :url
|
87
|
+
|
88
|
+
index :country
|
89
|
+
index :state
|
90
|
+
end
|
91
|
+
|
92
|
+
# Event log, for recording various things which happen on this web site.
|
93
|
+
# Every event contains what kind of object it refers to, what action was taken,
|
94
|
+
# what object was involved, if any, and arbitrary additional info stored as JSON.
|
95
|
+
|
96
|
+
table :events do
|
97
|
+
primary_key :id
|
98
|
+
|
99
|
+
# The kind of the object affected (like user or email)
|
100
|
+
String :kind
|
101
|
+
# What action was taken (like create or update)
|
102
|
+
String :action
|
103
|
+
|
104
|
+
# Id of the user the event relates to, if any.
|
105
|
+
foreign_key? :user_id, :users
|
106
|
+
# Id of the user responsible for creating the event, if any.
|
107
|
+
foreign_key? :author_id, :users
|
108
|
+
# Id of the object involved, whatever it is, for easier database lookup.
|
109
|
+
Unsigned? :subject_id
|
110
|
+
|
111
|
+
# IP of the request, if any.
|
112
|
+
String? :ip
|
113
|
+
|
114
|
+
# Arbitrary JSON encoded info.
|
115
|
+
Text :info
|
116
|
+
|
117
|
+
timestamps
|
118
|
+
|
119
|
+
index [ :kind, :action ]
|
120
|
+
index :user_id
|
121
|
+
index :author_id
|
122
|
+
index :subject_id
|
123
|
+
index :ip
|
124
|
+
index :create_time
|
125
|
+
end
|
126
|
+
|
127
|
+
# User's followers.
|
128
|
+
|
129
|
+
join_table :user_id, :user, :follower_id, :user, :user_followers
|
130
|
+
|
131
|
+
end
|
132
|
+
|
133
|
+
# EOF #
|
data/miguel.gemspec
CHANGED
@@ -4,11 +4,11 @@ require File.expand_path( '../lib/miguel/version', __FILE__ )
|
|
4
4
|
|
5
5
|
Gem::Specification.new do |s|
|
6
6
|
s.name = 'miguel'
|
7
|
-
s.version = Miguel::VERSION + '.
|
7
|
+
s.version = Miguel::VERSION + '.pre2'
|
8
8
|
s.summary = 'Database migrator and migration generator for Sequel.'
|
9
9
|
s.description = <<EOT
|
10
10
|
This gem makes it easy to create and maintain an up-to-date database schema
|
11
|
-
and apply it to the database as needed by the means of standard Sequel migrations.
|
11
|
+
and apply it to the database as needed by the means of standard Sequel migrations.
|
12
12
|
EOT
|
13
13
|
|
14
14
|
s.author = 'Patrik Rak'
|
@@ -19,6 +19,7 @@ EOT
|
|
19
19
|
s.files = `git ls-files`.split( "\n" )
|
20
20
|
s.executables = `git ls-files -- bin/*`.split( "\n" ).map{ |f| File.basename( f ) }
|
21
21
|
|
22
|
+
s.required_ruby_version = '>= 1.9.3'
|
22
23
|
s.add_runtime_dependency 'sequel', '~> 4.0'
|
23
24
|
s.add_development_dependency 'bacon', '~> 1.2'
|
24
25
|
end
|
data/test/test_dumper.rb
CHANGED
@@ -12,7 +12,7 @@ describe Miguel::Dumper do
|
|
12
12
|
d << "d"
|
13
13
|
d.text.should == "a\nb\nc\nd\n"
|
14
14
|
end
|
15
|
-
|
15
|
+
|
16
16
|
should 'support nesting' do
|
17
17
|
d = Miguel::Dumper.new
|
18
18
|
d.dump "test" do
|
@@ -36,7 +36,7 @@ test do
|
|
36
36
|
end
|
37
37
|
EOT
|
38
38
|
end
|
39
|
-
|
39
|
+
|
40
40
|
should 'support text interpolation' do
|
41
41
|
d = Miguel::Dumper.new
|
42
42
|
d << "abc"
|
@@ -44,7 +44,7 @@ EOT
|
|
44
44
|
d.text.should == d.to_s
|
45
45
|
d.text.should == "#{d}"
|
46
46
|
end
|
47
|
-
|
47
|
+
|
48
48
|
should 'accept nonstring arguments' do
|
49
49
|
d = Miguel::Dumper.new
|
50
50
|
d << 123
|
@@ -52,14 +52,14 @@ EOT
|
|
52
52
|
d << :test
|
53
53
|
d.text.should == "123\n0.5\ntest\n"
|
54
54
|
end
|
55
|
-
|
55
|
+
|
56
56
|
should 'support chaining' do
|
57
57
|
d = Miguel::Dumper.new
|
58
58
|
d.dump( "x" ).should == d
|
59
59
|
( d << "y" << "z" ).should == d
|
60
60
|
d.text.should == "x\ny\nz\n"
|
61
61
|
end
|
62
|
-
|
62
|
+
|
63
63
|
should 'support custom buffer' do
|
64
64
|
a = []
|
65
65
|
d = Miguel::Dumper.new( a )
|
@@ -68,7 +68,7 @@ EOT
|
|
68
68
|
a.should == [ "xyz\n", "abc\n" ]
|
69
69
|
d.text.should == "xyz\nabc\n"
|
70
70
|
end
|
71
|
-
|
71
|
+
|
72
72
|
should 'support configurable indentation' do
|
73
73
|
d = Miguel::Dumper.new( [], 4 )
|
74
74
|
d.dump "a" do
|
@@ -84,7 +84,7 @@ a do
|
|
84
84
|
end
|
85
85
|
EOT
|
86
86
|
end
|
87
|
-
|
87
|
+
|
88
88
|
end
|
89
89
|
|
90
90
|
# EOF #
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: miguel
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.0.
|
4
|
+
version: 0.1.0.pre2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Patrik Rak
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-09-
|
11
|
+
date: 2015-09-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: sequel
|
@@ -40,7 +40,7 @@ dependencies:
|
|
40
40
|
version: '1.2'
|
41
41
|
description: |
|
42
42
|
This gem makes it easy to create and maintain an up-to-date database schema
|
43
|
-
and apply it to the database as needed by the means of standard Sequel migrations.
|
43
|
+
and apply it to the database as needed by the means of standard Sequel migrations.
|
44
44
|
email: patrik@raxoft.cz
|
45
45
|
executables:
|
46
46
|
- miguel
|
@@ -48,9 +48,14 @@ extensions: []
|
|
48
48
|
extra_rdoc_files: []
|
49
49
|
files:
|
50
50
|
- ".gitignore"
|
51
|
+
- ".travis.gemfile"
|
52
|
+
- ".travis.yml"
|
53
|
+
- README.md
|
51
54
|
- Rakefile
|
52
55
|
- TODO
|
53
56
|
- bin/miguel
|
57
|
+
- examples/db.yml
|
58
|
+
- examples/schema.rb
|
54
59
|
- lib/miguel.rb
|
55
60
|
- lib/miguel/command.rb
|
56
61
|
- lib/miguel/dumper.rb
|
@@ -72,7 +77,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
72
77
|
requirements:
|
73
78
|
- - ">="
|
74
79
|
- !ruby/object:Gem::Version
|
75
|
-
version:
|
80
|
+
version: 1.9.3
|
76
81
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
77
82
|
requirements:
|
78
83
|
- - ">"
|