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.
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