systematize 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +69 -0
  3. data/lib/systematize/railtie.rb +11 -0
  4. data/lib/systematize/runner.rb +30 -0
  5. data/lib/systematize/version.rb +3 -0
  6. data/lib/systematize.rb +4 -0
  7. data/lib/tasks/migrations.rake +27 -0
  8. data/spec/spec_helper.rb +9 -0
  9. data/spec/support/db/data/20161117152453_mark_deleted_posts_with_timestamp.rb +15 -0
  10. data/spec/support/db/migrate/20161117151622_create_posts_table.rb +12 -0
  11. data/spec/support/db/migrate/20161117152138_add_deleted_at_timestamp.rb +9 -0
  12. data/spec/support/db/migrate/20161117152655_remove_deleted_column.rb +9 -0
  13. data/spec/systematize/runner_spec.rb +60 -0
  14. data/spec/testapp/Gemfile +41 -0
  15. data/spec/testapp/Gemfile.lock +128 -0
  16. data/spec/testapp/README.rdoc +261 -0
  17. data/spec/testapp/Rakefile +7 -0
  18. data/spec/testapp/app/assets/images/rails.png +0 -0
  19. data/spec/testapp/app/assets/javascripts/application.js +15 -0
  20. data/spec/testapp/app/assets/stylesheets/application.css +13 -0
  21. data/spec/testapp/app/controllers/application_controller.rb +3 -0
  22. data/spec/testapp/app/helpers/application_helper.rb +2 -0
  23. data/spec/testapp/app/models/post.rb +4 -0
  24. data/spec/testapp/app/views/layouts/application.html.erb +14 -0
  25. data/spec/testapp/config/application.rb +59 -0
  26. data/spec/testapp/config/boot.rb +6 -0
  27. data/spec/testapp/config/database.yml +25 -0
  28. data/spec/testapp/config/environment.rb +5 -0
  29. data/spec/testapp/config/environments/development.rb +37 -0
  30. data/spec/testapp/config/environments/production.rb +67 -0
  31. data/spec/testapp/config/environments/test.rb +37 -0
  32. data/spec/testapp/config/initializers/backtrace_silencers.rb +7 -0
  33. data/spec/testapp/config/initializers/inflections.rb +15 -0
  34. data/spec/testapp/config/initializers/mime_types.rb +5 -0
  35. data/spec/testapp/config/initializers/secret_token.rb +7 -0
  36. data/spec/testapp/config/initializers/session_store.rb +8 -0
  37. data/spec/testapp/config/initializers/wrap_parameters.rb +14 -0
  38. data/spec/testapp/config/locales/en.yml +5 -0
  39. data/spec/testapp/config/routes.rb +58 -0
  40. data/spec/testapp/config.ru +4 -0
  41. data/spec/testapp/db/data/20161117152453_mark_deleted_posts_with_timestamp.rb +15 -0
  42. data/spec/testapp/db/development.sqlite3 +0 -0
  43. data/spec/testapp/db/migrate/20161117151622_create_posts_table.rb +12 -0
  44. data/spec/testapp/db/migrate/20161117152138_add_deleted_at_timestamp.rb +9 -0
  45. data/spec/testapp/db/migrate/20161117152655_remove_deleted_column.rb +9 -0
  46. data/spec/testapp/db/seeds.rb +7 -0
  47. data/spec/testapp/db/test.sqlite3 +0 -0
  48. data/spec/testapp/doc/README_FOR_APP +2 -0
  49. data/spec/testapp/log/development.log +953 -0
  50. data/spec/testapp/public/404.html +26 -0
  51. data/spec/testapp/public/422.html +26 -0
  52. data/spec/testapp/public/500.html +25 -0
  53. data/spec/testapp/public/favicon.ico +0 -0
  54. data/spec/testapp/public/index.html +241 -0
  55. data/spec/testapp/public/robots.txt +5 -0
  56. data/spec/testapp/script/rails +6 -0
  57. data/spec/testapp/test/performance/browsing_test.rb +12 -0
  58. data/spec/testapp/test/test_helper.rb +13 -0
  59. 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
+ ![shuffler.gif](https://s15.postimg.org/jupy0v0or/shuffler.gif)
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,11 @@
1
+ require 'systematize'
2
+
3
+ module Systematize
4
+ class Railtie < Rails::Railtie
5
+ railtie_name :systematize
6
+
7
+ rake_tasks do
8
+ load 'tasks/migrations.rake'
9
+ end
10
+ end
11
+ end
@@ -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
@@ -0,0 +1,3 @@
1
+ module Systematize
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,4 @@
1
+ module Systematize
2
+ require 'systematize/railtie'
3
+ require 'systematize/runner'
4
+ end
@@ -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
@@ -0,0 +1,9 @@
1
+ require 'rspec'
2
+ require 'rails'
3
+ require 'systematize'
4
+ require 'pry'
5
+
6
+ RSpec.configure do |config|
7
+ config.color = true
8
+ config.tty = true
9
+ end
@@ -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,12 @@
1
+ class CreatePostsTable < ActiveRecord::Migration
2
+ def change
3
+ create_table :posts do |p|
4
+ p.string :title
5
+ p.string :description
6
+ p.integer :owner_id
7
+ p.boolean :deleted
8
+
9
+ p.timestamps
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,9 @@
1
+ class AddDeletedAtTimestamp < ActiveRecord::Migration
2
+ def up
3
+ add_column :posts, :deleted_at, :time
4
+ end
5
+
6
+ def down
7
+ remove_column :posts, :deleted_at
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ class RemoveDeletedColumn < ActiveRecord::Migration
2
+ def up
3
+ remove_column :posts, :deleted
4
+ end
5
+
6
+ def down
7
+ add_column :posts, :deleted, :boolean
8
+ end
9
+ 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