systematize 0.0.1
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/README.md +69 -0
- data/lib/systematize/railtie.rb +11 -0
- data/lib/systematize/runner.rb +30 -0
- data/lib/systematize/version.rb +3 -0
- data/lib/systematize.rb +4 -0
- data/lib/tasks/migrations.rake +27 -0
- data/spec/spec_helper.rb +9 -0
- data/spec/support/db/data/20161117152453_mark_deleted_posts_with_timestamp.rb +15 -0
- data/spec/support/db/migrate/20161117151622_create_posts_table.rb +12 -0
- data/spec/support/db/migrate/20161117152138_add_deleted_at_timestamp.rb +9 -0
- data/spec/support/db/migrate/20161117152655_remove_deleted_column.rb +9 -0
- data/spec/systematize/runner_spec.rb +60 -0
- data/spec/testapp/Gemfile +41 -0
- data/spec/testapp/Gemfile.lock +128 -0
- data/spec/testapp/README.rdoc +261 -0
- data/spec/testapp/Rakefile +7 -0
- data/spec/testapp/app/assets/images/rails.png +0 -0
- data/spec/testapp/app/assets/javascripts/application.js +15 -0
- data/spec/testapp/app/assets/stylesheets/application.css +13 -0
- data/spec/testapp/app/controllers/application_controller.rb +3 -0
- data/spec/testapp/app/helpers/application_helper.rb +2 -0
- data/spec/testapp/app/models/post.rb +4 -0
- data/spec/testapp/app/views/layouts/application.html.erb +14 -0
- data/spec/testapp/config/application.rb +59 -0
- data/spec/testapp/config/boot.rb +6 -0
- data/spec/testapp/config/database.yml +25 -0
- data/spec/testapp/config/environment.rb +5 -0
- data/spec/testapp/config/environments/development.rb +37 -0
- data/spec/testapp/config/environments/production.rb +67 -0
- data/spec/testapp/config/environments/test.rb +37 -0
- data/spec/testapp/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/testapp/config/initializers/inflections.rb +15 -0
- data/spec/testapp/config/initializers/mime_types.rb +5 -0
- data/spec/testapp/config/initializers/secret_token.rb +7 -0
- data/spec/testapp/config/initializers/session_store.rb +8 -0
- data/spec/testapp/config/initializers/wrap_parameters.rb +14 -0
- data/spec/testapp/config/locales/en.yml +5 -0
- data/spec/testapp/config/routes.rb +58 -0
- data/spec/testapp/config.ru +4 -0
- data/spec/testapp/db/data/20161117152453_mark_deleted_posts_with_timestamp.rb +15 -0
- data/spec/testapp/db/development.sqlite3 +0 -0
- data/spec/testapp/db/migrate/20161117151622_create_posts_table.rb +12 -0
- data/spec/testapp/db/migrate/20161117152138_add_deleted_at_timestamp.rb +9 -0
- data/spec/testapp/db/migrate/20161117152655_remove_deleted_column.rb +9 -0
- data/spec/testapp/db/seeds.rb +7 -0
- data/spec/testapp/db/test.sqlite3 +0 -0
- data/spec/testapp/doc/README_FOR_APP +2 -0
- data/spec/testapp/log/development.log +953 -0
- data/spec/testapp/public/404.html +26 -0
- data/spec/testapp/public/422.html +26 -0
- data/spec/testapp/public/500.html +25 -0
- data/spec/testapp/public/favicon.ico +0 -0
- data/spec/testapp/public/index.html +241 -0
- data/spec/testapp/public/robots.txt +5 -0
- data/spec/testapp/script/rails +6 -0
- data/spec/testapp/test/performance/browsing_test.rb +12 -0
- data/spec/testapp/test/test_helper.rb +13 -0
- metadata +209 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 39619b8bfa011bf992c002bf266e3cc87e074d0c
|
4
|
+
data.tar.gz: 5a1f88232472a5ec70e5d795448b59a93f5beb7d
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 51c3ab97157d5853c4c1d55e9d92396212094d7669b115d30ba0ae1438cfbc3c1ad216af673711cba9745ac8c40bfc229039416b14dc42608d2ea7a4ad65dbf5
|
7
|
+
data.tar.gz: 2ab08ea9995723e086409e78fe4741a0386b7a16cacb332e4f1b9c33bd0a409bf4180eb686e10460daddfdc8f42aef81d150ef65805e4360fdff3532d944c354
|
data/README.md
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
# systematize
|
2
|
+
|
3
|
+

|
4
|
+
|
5
|
+
One of the most important things that a ruby application can have are the migrations, but they can be one of 2 kinds:
|
6
|
+
- Structural migrations
|
7
|
+
- Data migrations
|
8
|
+
|
9
|
+
If you want to organize said migrations in their purpose you'll probably have a folder for the struture ones and another for the data ones. But with that separation comes a problem, when should you run one type and when to run the other?
|
10
|
+
Probably the sanner way of doing it is we firstly run the structure migrations and after that we run the data migrations, but with this approach one problem will rise:
|
11
|
+
|
12
|
+
What if I have a new field that is initially populated taking into account another field, and after that we can delete that other field?
|
13
|
+
Imagine the following scenario:
|
14
|
+
- You have a `Post` model that initially has a boolean field called `:deleted`.
|
15
|
+
- After some time, and some deleted `Posts`, you need to know when that post has been deleted. So you create a `:deleted_at` field that will contain the time os the deletion.
|
16
|
+
- You can now delete the old `:deleted` field because it turned obsolete, so you create the migration to do it.
|
17
|
+
|
18
|
+
On this scenario we will have 2 structure migrations (create the `:deleted_at` field and removing the `:deleted` field) and a data migration (go through all the Posts and add the time to `:deleted_at` if they are `:deleted`). With previous migration approach, running all the migrations would fail because when the data migration run we would have the `:deleted` field because it was deleted by the structure migration.
|
19
|
+
|
20
|
+
This is when `systematize` comes in for the rescue 🚀
|
21
|
+
|
22
|
+
## Installation
|
23
|
+
|
24
|
+
If your using a Gemfile, just add it to your project
|
25
|
+
<pre><code>#Gemfile
|
26
|
+
gem 'systematize'
|
27
|
+
</code></pre>
|
28
|
+
|
29
|
+
Or just add it via `bundler`
|
30
|
+
<pre><code>bundle install 'systematize'</code></pre>
|
31
|
+
|
32
|
+
## Structure
|
33
|
+
So as the structural migrations live in the `db/migrate` folder, the data migrations shall live in the `db/data` folder:
|
34
|
+
|
35
|
+
<pre><code>- app
|
36
|
+
|
|
37
|
+
|-db
|
38
|
+
|-data
|
39
|
+
|-migrate
|
40
|
+
</pre></code>
|
41
|
+
|
42
|
+
## Usage
|
43
|
+
After installing you'll se the following tasks pop-up:
|
44
|
+
|
45
|
+
<pre><code>$> bundle exec rake -T
|
46
|
+
rake systematize:migrate # Migrate the database
|
47
|
+
rake systematize:rollback # Rollback the database (options: STEP=x, VERBOSE=false)
|
48
|
+
rake systematize:rollback_all # Rollback all the database
|
49
|
+
</pre></code>
|
50
|
+
|
51
|
+
Now if you need to migrate the database you just need to run:
|
52
|
+
<pre><code>bundle exec rake systematize:migrate</pre></code>
|
53
|
+
|
54
|
+
Needing to rollback the previous migration? No problem.
|
55
|
+
<pre><code>bundle exec rake systematize:rollback</pre></code>
|
56
|
+
|
57
|
+
Need to rollback 2/3/4 migrations? I got you.
|
58
|
+
<pre><code>bundle exec rake systematize:rollback STEP=2 </pre></code>
|
59
|
+
|
60
|
+
Made a mess so big you need to start fresh? Do it. (the migrations need to be reversible :smile:)
|
61
|
+
<pre><code>bundle exec rake systematize:rollback_all </pre></code>
|
62
|
+
|
63
|
+
## Caveats
|
64
|
+
- The migrations need to follow the Rails convention to them `YYYYMMDDHHMMSS_create_products.rb`
|
65
|
+
- The migrations are wrapped around a `ActiveRecord::Base.transaction`, so if any of the migration fails the batch of migrations will rollback, until the previous successful batch.
|
66
|
+
|
67
|
+
## TODO
|
68
|
+
- [ ] Customizable folder configuration
|
69
|
+
- [ ] Customizable transaction type configuration
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Systematize
|
2
|
+
class Runner
|
3
|
+
|
4
|
+
DB_FOLDER_PATH = "#{Rack::Directory.new('').root}/db"
|
5
|
+
DATA_MIGRATIONS_PATH = "#{DB_FOLDER_PATH}/data"
|
6
|
+
STRUCTURE_MIGRATIONS_PATH = "#{DB_FOLDER_PATH}/migrate"
|
7
|
+
TEMP_MIGRATIONS_FOLDER_PATH = "#{DB_FOLDER_PATH}/tmp"
|
8
|
+
|
9
|
+
def self.run(&block)
|
10
|
+
|
11
|
+
# Create temporary folder where all the migrations will be
|
12
|
+
FileUtils.mkdir(TEMP_MIGRATIONS_FOLDER_PATH)
|
13
|
+
|
14
|
+
#copy all the files to a temporary folder
|
15
|
+
FileUtils.cp_r(Dir.glob("#{STRUCTURE_MIGRATIONS_PATH}/*.rb"), TEMP_MIGRATIONS_FOLDER_PATH)
|
16
|
+
FileUtils.cp_r(Dir.glob("#{DATA_MIGRATIONS_PATH}/*.rb"), TEMP_MIGRATIONS_FOLDER_PATH)
|
17
|
+
|
18
|
+
ActiveRecord::Base.transaction do
|
19
|
+
yield(TEMP_MIGRATIONS_FOLDER_PATH)
|
20
|
+
end
|
21
|
+
|
22
|
+
rescue Exception => e
|
23
|
+
raise e
|
24
|
+
|
25
|
+
ensure
|
26
|
+
# Remove the temporary folder
|
27
|
+
FileUtils.rm_rf(TEMP_MIGRATIONS_FOLDER_PATH)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
data/lib/systematize.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
namespace :systematize do
|
2
|
+
desc "Migrate the database"
|
3
|
+
task :migrate => :environment do
|
4
|
+
Systematize::Runner.run do |temp_folder|
|
5
|
+
ActiveRecord::Migration.verbose = ENV["VERBOSE"] || "true"
|
6
|
+
ActiveRecord::Migrator.migrate(temp_folder)
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
desc "Rollback the database (options: STEP=x, VERBOSE=false)"
|
11
|
+
task :rollback => :environment do
|
12
|
+
Systematize::Runner.run do |temp_folder|
|
13
|
+
steps = ENV["STEP"] ? ENV["STEP"].to_i : 1
|
14
|
+
|
15
|
+
ActiveRecord::Migration.verbose = ENV["VERBOSE"] || "true"
|
16
|
+
ActiveRecord::Migrator.rollback(temp_folder, steps)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
desc "Rollback all the database"
|
21
|
+
task :rollback_all => :environment do
|
22
|
+
Systematize::Runner.run do |temp_folder|
|
23
|
+
ActiveRecord::Migration.verbose = ENV["VERBOSE"] || "true"
|
24
|
+
ActiveRecord::Migrator.migrate(temp_folder, 0)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
class MarkDeletedPostsWithTimestamp < ActiveRecord::Migration
|
2
|
+
def up
|
3
|
+
Post.where(deleted: true).each do |post|
|
4
|
+
post.deleted_at = Time.now
|
5
|
+
post.save
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
def down
|
10
|
+
Post.where("deleted_at != ?", nil).each do |post|
|
11
|
+
post.deleted = true
|
12
|
+
post.save
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Systematize::Runner do
|
4
|
+
|
5
|
+
describe '#run' do
|
6
|
+
|
7
|
+
subject{
|
8
|
+
described_class.run do |temp_folder|
|
9
|
+
"The temp folder is at #{temp_folder}"
|
10
|
+
end
|
11
|
+
}
|
12
|
+
|
13
|
+
before do
|
14
|
+
|
15
|
+
stub_const('Systematize::Runner::DB_FOLDER_PATH', './spec/support/db')
|
16
|
+
stub_const('Systematize::Runner::DATA_MIGRATIONS_PATH', "#{Systematize::Runner::DB_FOLDER_PATH}/data")
|
17
|
+
stub_const('Systematize::Runner::STRUCTURE_MIGRATIONS_PATH', "#{Systematize::Runner::DB_FOLDER_PATH}/migrate")
|
18
|
+
stub_const('Systematize::Runner::TEMP_MIGRATIONS_FOLDER_PATH', "#{Systematize::Runner::DB_FOLDER_PATH}/tmp")
|
19
|
+
|
20
|
+
allow(FileUtils).to receive(:mkdir).and_call_original
|
21
|
+
allow(FileUtils).to receive(:rm_rf).and_call_original
|
22
|
+
allow(FileUtils).to receive(:cp_r).and_call_original
|
23
|
+
|
24
|
+
subject
|
25
|
+
end
|
26
|
+
|
27
|
+
|
28
|
+
it 'creates a temp folder where all the migrations will be' do
|
29
|
+
expect(FileUtils).to have_received(:mkdir).once
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'deletes the temp folder where all the migrations were' do
|
33
|
+
expect(FileUtils).to have_received(:rm_rf).once
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'copies the content of /db/migrate to /db/temp' do
|
37
|
+
expect(FileUtils)
|
38
|
+
.to have_received(:cp_r)
|
39
|
+
.with(Dir.glob("#{Systematize::Runner::STRUCTURE_MIGRATIONS_PATH}/*.rb"), Systematize::Runner::TEMP_MIGRATIONS_FOLDER_PATH)
|
40
|
+
.once
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'copies the content of /db/data to /db/temp' do
|
44
|
+
expect(FileUtils)
|
45
|
+
.to have_received(:cp_r)
|
46
|
+
.with(Dir.glob("#{Systematize::Runner::DATA_MIGRATIONS_PATH}/*.rb"), Systematize::Runner::TEMP_MIGRATIONS_FOLDER_PATH)
|
47
|
+
.once
|
48
|
+
end
|
49
|
+
|
50
|
+
# Test if #run yields the block that it receives
|
51
|
+
specify{
|
52
|
+
expect{ |b|
|
53
|
+
described_class.run(&b)
|
54
|
+
}
|
55
|
+
.to yield_with_args(Systematize::Runner::TEMP_MIGRATIONS_FOLDER_PATH)
|
56
|
+
}
|
57
|
+
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
source 'https://rubygems.org'
|
2
|
+
|
3
|
+
gem 'rails', '3.2.0'
|
4
|
+
|
5
|
+
# Bundle edge Rails instead:
|
6
|
+
# gem 'rails', :git => 'git://github.com/rails/rails.git'
|
7
|
+
|
8
|
+
gem 'sqlite3'
|
9
|
+
|
10
|
+
gem 'systematize', path: '../../../systematize'
|
11
|
+
|
12
|
+
gem 'pry'
|
13
|
+
|
14
|
+
# Gems used only for assets and not required
|
15
|
+
# in production environments by default.
|
16
|
+
group :assets do
|
17
|
+
gem 'sass-rails', '~> 3.2.3'
|
18
|
+
gem 'coffee-rails', '~> 3.2.1'
|
19
|
+
|
20
|
+
# See https://github.com/sstephenson/execjs#readme for more supported runtimes
|
21
|
+
# gem 'therubyracer'
|
22
|
+
|
23
|
+
gem 'uglifier', '>= 1.0.3'
|
24
|
+
end
|
25
|
+
|
26
|
+
gem 'jquery-rails'
|
27
|
+
|
28
|
+
# To use ActiveModel has_secure_password
|
29
|
+
# gem 'bcrypt-ruby', '~> 3.0.0'
|
30
|
+
|
31
|
+
# To use Jbuilder templates for JSON
|
32
|
+
# gem 'jbuilder'
|
33
|
+
|
34
|
+
# Use unicorn as the web server
|
35
|
+
# gem 'unicorn'
|
36
|
+
|
37
|
+
# Deploy with Capistrano
|
38
|
+
# gem 'capistrano'
|
39
|
+
|
40
|
+
# To use debugger
|
41
|
+
# gem 'ruby-debug19', :require => 'ruby-debug'
|
@@ -0,0 +1,128 @@
|
|
1
|
+
PATH
|
2
|
+
remote: ../../../systematize
|
3
|
+
specs:
|
4
|
+
systematize (0.0.1)
|
5
|
+
activerecord
|
6
|
+
railties
|
7
|
+
|
8
|
+
GEM
|
9
|
+
remote: https://rubygems.org/
|
10
|
+
specs:
|
11
|
+
actionmailer (3.2.0)
|
12
|
+
actionpack (= 3.2.0)
|
13
|
+
mail (~> 2.4.0)
|
14
|
+
actionpack (3.2.0)
|
15
|
+
activemodel (= 3.2.0)
|
16
|
+
activesupport (= 3.2.0)
|
17
|
+
builder (~> 3.0.0)
|
18
|
+
erubis (~> 2.7.0)
|
19
|
+
journey (~> 1.0.0)
|
20
|
+
rack (~> 1.4.0)
|
21
|
+
rack-cache (~> 1.1)
|
22
|
+
rack-test (~> 0.6.1)
|
23
|
+
sprockets (~> 2.1.2)
|
24
|
+
activemodel (3.2.0)
|
25
|
+
activesupport (= 3.2.0)
|
26
|
+
builder (~> 3.0.0)
|
27
|
+
activerecord (3.2.0)
|
28
|
+
activemodel (= 3.2.0)
|
29
|
+
activesupport (= 3.2.0)
|
30
|
+
arel (~> 3.0.0)
|
31
|
+
tzinfo (~> 0.3.29)
|
32
|
+
activeresource (3.2.0)
|
33
|
+
activemodel (= 3.2.0)
|
34
|
+
activesupport (= 3.2.0)
|
35
|
+
activesupport (3.2.0)
|
36
|
+
i18n (~> 0.6)
|
37
|
+
multi_json (~> 1.0)
|
38
|
+
arel (3.0.3)
|
39
|
+
builder (3.0.4)
|
40
|
+
coderay (1.1.1)
|
41
|
+
coffee-rails (3.2.2)
|
42
|
+
coffee-script (>= 2.2.0)
|
43
|
+
railties (~> 3.2.0)
|
44
|
+
coffee-script (2.4.1)
|
45
|
+
coffee-script-source
|
46
|
+
execjs
|
47
|
+
coffee-script-source (1.10.0)
|
48
|
+
erubis (2.7.0)
|
49
|
+
execjs (2.7.0)
|
50
|
+
hike (1.2.3)
|
51
|
+
i18n (0.7.0)
|
52
|
+
journey (1.0.4)
|
53
|
+
jquery-rails (3.1.4)
|
54
|
+
railties (>= 3.0, < 5.0)
|
55
|
+
thor (>= 0.14, < 2.0)
|
56
|
+
json (1.8.3)
|
57
|
+
mail (2.4.4)
|
58
|
+
i18n (>= 0.4.0)
|
59
|
+
mime-types (~> 1.16)
|
60
|
+
treetop (~> 1.4.8)
|
61
|
+
method_source (0.8.2)
|
62
|
+
mime-types (1.25.1)
|
63
|
+
multi_json (1.12.1)
|
64
|
+
polyglot (0.3.5)
|
65
|
+
pry (0.10.4)
|
66
|
+
coderay (~> 1.1.0)
|
67
|
+
method_source (~> 0.8.1)
|
68
|
+
slop (~> 3.4)
|
69
|
+
rack (1.4.7)
|
70
|
+
rack-cache (1.6.1)
|
71
|
+
rack (>= 0.4)
|
72
|
+
rack-ssl (1.3.4)
|
73
|
+
rack
|
74
|
+
rack-test (0.6.3)
|
75
|
+
rack (>= 1.0)
|
76
|
+
rails (3.2.0)
|
77
|
+
actionmailer (= 3.2.0)
|
78
|
+
actionpack (= 3.2.0)
|
79
|
+
activerecord (= 3.2.0)
|
80
|
+
activeresource (= 3.2.0)
|
81
|
+
activesupport (= 3.2.0)
|
82
|
+
bundler (~> 1.0)
|
83
|
+
railties (= 3.2.0)
|
84
|
+
railties (3.2.0)
|
85
|
+
actionpack (= 3.2.0)
|
86
|
+
activesupport (= 3.2.0)
|
87
|
+
rack-ssl (~> 1.3.2)
|
88
|
+
rake (>= 0.8.7)
|
89
|
+
rdoc (~> 3.4)
|
90
|
+
thor (~> 0.14.6)
|
91
|
+
rake (11.3.0)
|
92
|
+
rdoc (3.12.2)
|
93
|
+
json (~> 1.4)
|
94
|
+
sass (3.4.22)
|
95
|
+
sass-rails (3.2.6)
|
96
|
+
railties (~> 3.2.0)
|
97
|
+
sass (>= 3.1.10)
|
98
|
+
tilt (~> 1.3)
|
99
|
+
slop (3.6.0)
|
100
|
+
sprockets (2.1.4)
|
101
|
+
hike (~> 1.2)
|
102
|
+
rack (~> 1.0)
|
103
|
+
tilt (~> 1.1, != 1.3.0)
|
104
|
+
sqlite3 (1.3.12)
|
105
|
+
thor (0.14.6)
|
106
|
+
tilt (1.4.1)
|
107
|
+
treetop (1.4.15)
|
108
|
+
polyglot
|
109
|
+
polyglot (>= 0.3.1)
|
110
|
+
tzinfo (0.3.52)
|
111
|
+
uglifier (3.0.3)
|
112
|
+
execjs (>= 0.3.0, < 3)
|
113
|
+
|
114
|
+
PLATFORMS
|
115
|
+
ruby
|
116
|
+
|
117
|
+
DEPENDENCIES
|
118
|
+
coffee-rails (~> 3.2.1)
|
119
|
+
jquery-rails
|
120
|
+
pry
|
121
|
+
rails (= 3.2.0)
|
122
|
+
sass-rails (~> 3.2.3)
|
123
|
+
sqlite3
|
124
|
+
systematize!
|
125
|
+
uglifier (>= 1.0.3)
|
126
|
+
|
127
|
+
BUNDLED WITH
|
128
|
+
1.13.6
|