db_auto_migrations 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: df6c792de2c4c0f0b66a8b3820e90c3009a50cdbce199fd1131cb0de91e6d0cc
4
+ data.tar.gz: 67a006293c936f44c594180e32510fa4dba8b97fef80a8aac436316c4ab3c870
5
+ SHA512:
6
+ metadata.gz: 93296e2066d8659e27f97bea67ddbbf3d8629f8203e8302d8fc9d608c4e216992c36a336fc07a50cf25272044faff5c64c804003cb0f49a94948b5b90c37c2ee
7
+ data.tar.gz: ff3cb880fb309b4c50628aa9c4a3b1f5c80584bf09f4ba76ec96378bd51428ff70e2356be0f6f63ccb841190a50733cce38c38e31794f61a46fe2b23d9383f3e
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ lib/**/*.rb
2
+ bin/*
3
+ -
4
+ features/**/*.feature
5
+ LICENSE.txt
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2021 sai
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 ADDED
@@ -0,0 +1,46 @@
1
+ == AutoMigrations
2
+
3
+ Forget migrations, auto-migrate!
4
+
5
+
6
+ == Usage
7
+
8
+ Write out your schema (or use an existing one)
9
+
10
+ $ cat db/schema.rb
11
+
12
+ ActiveRecord::Schema.define do
13
+
14
+ create_table :posts do |t|
15
+ t.string :title
16
+ t.text :body
17
+ t.timestamps
18
+ end
19
+
20
+ end
21
+
22
+ $ rake db:auto:migrate
23
+
24
+ Created posts table
25
+
26
+ ...a few days later
27
+
28
+ $ cat db/schema.rb
29
+
30
+ ActiveRecord::Schema.define do
31
+
32
+ create_table :posts do |t|
33
+ t.string :title
34
+ t.text :content
35
+ t.timestamps
36
+ end
37
+
38
+ end
39
+
40
+ $ rake db:auto:migrate
41
+ -- add_column("posts", :content, :text)
42
+ -> 0.0307s
43
+ -- remove_column("posts", "body")
44
+ -> 0.0311s
45
+
46
+ * PJ Hyett [ pjhyett@gmail.com ]
data/Rakefile ADDED
@@ -0,0 +1,40 @@
1
+ require 'rake'
2
+ require 'rubygems'
3
+ require 'rake/testtask'
4
+ require 'rdoc/task'
5
+
6
+ begin
7
+ require 'jeweler'
8
+ Jeweler::Tasks.new do |gemspec|
9
+ gemspec.name = "db_auto_migrations"
10
+ gemspec.summary = "Auto database migration."
11
+ gemspec.description = "Auto database migration."
12
+ gemspec.email = "rubyer1993@gmail.com"
13
+ gemspec.homepage = "https://github.com/sai1024/auto_migrations"
14
+ gemspec.authors = ["sai (originally by PJ Hyett)"]
15
+ end
16
+ Jeweler::GemcutterTasks.new
17
+ rescue LoadError
18
+ puts "Jeweler not available. Install it with: sudo gem install jeweler -s http://gemcutter.org"
19
+ end
20
+
21
+ desc 'Default: run unit tests.'
22
+ task :default => :test
23
+
24
+ desc 'Test the auto_migrations plugin.'
25
+ Rake::TestTask.new(:test) do |t|
26
+ t.libs << 'lib'
27
+ t.pattern = 'test/**/*_test.rb'
28
+ t.verbose = true
29
+ end
30
+
31
+ desc 'Generate documentation for the auto_migrations plugin.'
32
+ Rake::RDocTask.new(:rdoc) do |rdoc|
33
+ files = ['README', 'LICENSE', 'lib/**/*.rb']
34
+ rdoc.rdoc_files.add(files)
35
+ rdoc.main = "README" # page to start on
36
+ rdoc.title = "auto_migrations"
37
+ rdoc.template = File.exists?(t="/Users/chris/ruby/projects/err/rock/template.rb") ? t : "/var/www/rock/template.rb"
38
+ rdoc.rdoc_dir = 'doc' # rdoc output folder
39
+ rdoc.options << '--inline-source'
40
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 1.0.1
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,39 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+ # stub: db_auto_migrations 1.0.1 ruby lib
6
+
7
+ Gem::Specification.new do |s|
8
+ s.name = "db_auto_migrations".freeze
9
+ s.version = "1.0.1"
10
+
11
+ s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
12
+ s.require_paths = ["lib".freeze]
13
+ s.authors = ["sai (originally by PJ Hyett)".freeze]
14
+ s.date = "2021-12-07"
15
+ s.description = "Auto database migration.".freeze
16
+ s.email = "rubyer1993@gmail.com".freeze
17
+ s.executables = ["setup".freeze]
18
+ s.extra_rdoc_files = [
19
+ "LICENSE",
20
+ "README"
21
+ ]
22
+ s.files = [
23
+ ".document",
24
+ "LICENSE",
25
+ "README",
26
+ "Rakefile",
27
+ "VERSION",
28
+ "bin/setup",
29
+ "db_auto_migrations.gemspec",
30
+ "init.rb",
31
+ "lib/db_auto_migrations.rb",
32
+ "lib/tasks/db_auto_migrations_tasks.rake",
33
+ "test/db_auto_migrations_test.rb"
34
+ ]
35
+ s.homepage = "https://github.com/sai1024/auto_migrations".freeze
36
+ s.rubygems_version = "3.0.9".freeze
37
+ s.summary = "Auto database migration.".freeze
38
+ end
39
+
data/init.rb ADDED
@@ -0,0 +1 @@
1
+ require 'auto_migrations'
@@ -0,0 +1,194 @@
1
+ # load rake
2
+ Dir[File.join(File.dirname(__FILE__),'tasks/**/*.rake')].each { |f| load f } if defined?(Rake)
3
+
4
+ module AutoMigrations
5
+
6
+ def self.run
7
+ # Turn off schema_info code for auto-migration
8
+ class << ActiveRecord::Schema
9
+ alias :old_define :define
10
+ attr_accessor :version
11
+ def define(info={}, &block) @version = Time.now.utc.strftime("%Y%m%d%H%M%S"); instance_eval(&block) end
12
+ end
13
+
14
+ load(File.join(Rails.root, 'db', 'schema.rb'))
15
+ ActiveRecord::Migration.drop_unused_tables
16
+ ActiveRecord::Migration.drop_unused_indexes
17
+ ActiveRecord::Migration.update_schema_version(ActiveRecord::Schema.version) if ActiveRecord::Schema.version
18
+
19
+ class << ActiveRecord::Schema
20
+ alias :define :old_define
21
+ end
22
+ end
23
+
24
+ def self.schema_to_migration(with_reset = false)
25
+ schema_in = File.read(File.join(Rails.root, "db", "schema.rb"))
26
+ schema_in.gsub!(/#(.)+\n/, '')
27
+ schema_in.sub!(/ActiveRecord::Schema.define(.+)do[ ]?\n/, '')
28
+ schema_in.gsub!(/^/, ' ')
29
+ schema = "class InitialSchema < ActiveRecord::Migration\n def self.up\n"
30
+ schema += " # We're resetting the migrations database...\n" +
31
+ " drop_table :schema_migrations\n" +
32
+ " initialize_schema_migrations_table\n\n" if with_reset
33
+ schema += schema_in
34
+ schema << "\n def self.down\n"
35
+ schema << (ActiveRecord::Base.connection.tables - %w(schema_info schema_migrations)).map do |table|
36
+ " drop_table :#{table}\n"
37
+ end.join
38
+ schema << " end\nend\n"
39
+ migration_file = File.join(Rails.root, "db", "migrate", "001_initial_schema.rb")
40
+ File.open(migration_file, "w") { |f| f << schema }
41
+ puts "Migration created at db/migrate/001_initial_schema.rb"
42
+ end
43
+
44
+ def self.included(base)
45
+ base.extend ClassMethods
46
+ class << base
47
+ cattr_accessor :tables_in_schema, :indexes_in_schema
48
+ self.tables_in_schema, self.indexes_in_schema = [], []
49
+ alias_method_chain :method_missing, :auto_migration
50
+ end
51
+ end
52
+
53
+ module ClassMethods
54
+
55
+ def method_missing_with_auto_migration(method, *args, &block)
56
+ case method
57
+ when :create_table
58
+ auto_create_table(method, *args, &block)
59
+ when :add_index
60
+ auto_add_index(method, *args, &block)
61
+ else
62
+ method_missing_without_auto_migration(method, *args, &block)
63
+ end
64
+ end
65
+
66
+ def auto_create_table(method, *args, &block)
67
+ table_name = args.shift.to_s
68
+ options = args.pop || {}
69
+
70
+ (self.tables_in_schema ||= []) << table_name
71
+
72
+ # Table doesn't exist, create it
73
+ unless ActiveRecord::Base.connection.tables.include?(table_name)
74
+ return method_missing_without_auto_migration(method, *[table_name, options], &block)
75
+ end
76
+
77
+ # Grab database columns
78
+ fields_in_db = ActiveRecord::Base.connection.columns(table_name).inject({}) do |hash, column|
79
+ hash[column.name] = column
80
+ hash
81
+ end
82
+
83
+ # Grab schema columns (lifted from active_record/connection_adapters/abstract/schema_statements.rb)
84
+ table_definition = ActiveRecord::ConnectionAdapters::TableDefinition.new(ActiveRecord::Base.connection)
85
+ primary_key = options[:primary_key] || "id"
86
+ table_definition.primary_key(primary_key) unless options[:id] == false
87
+ yield table_definition
88
+ fields_in_schema = table_definition.columns.inject({}) do |hash, column|
89
+ hash[column.name.to_s] = column
90
+ hash
91
+ end
92
+
93
+ # Add fields to db new to schema
94
+ (fields_in_schema.keys - fields_in_db.keys).each do |field|
95
+ column = fields_in_schema[field]
96
+ options = {:limit => column.limit, :precision => column.precision, :scale => column.scale}
97
+ options[:default] = column.default if !column.default.nil?
98
+ options[:null] = column.null if !column.null.nil?
99
+ add_column table_name, column.name, column.type.to_sym, options
100
+ end
101
+
102
+ # Remove fields from db no longer in schema
103
+ (fields_in_db.keys - fields_in_schema.keys & fields_in_db.keys).each do |field|
104
+ column = fields_in_db[field]
105
+ remove_column table_name, column.name
106
+ end
107
+
108
+ (fields_in_schema.keys & fields_in_db.keys).each do |field|
109
+ if field != primary_key #ActiveRecord::Base.get_primary_key(table_name)
110
+ changed = false # flag
111
+ new_type = fields_in_schema[field].type.to_sym
112
+ new_attr = {}
113
+
114
+ # First, check if the field type changed
115
+ if fields_in_schema[field].type.to_sym != fields_in_db[field].type.to_sym
116
+ changed = true
117
+ end
118
+
119
+ # Special catch for precision/scale, since *both* must be specified together
120
+ # Always include them in the attr struct, but they'll only get applied if changed = true
121
+ new_attr[:precision] = fields_in_schema[field][:precision]
122
+ new_attr[:scale] = fields_in_schema[field][:scale]
123
+
124
+ # Next, iterate through our extended attributes, looking for any differences
125
+ # This catches stuff like :null, :precision, etc
126
+ fields_in_schema[field].each_pair do |att,value|
127
+ next if att == :type or att == :base or att == :name # special cases
128
+ if !value.nil?
129
+ value_in_db = fields_in_db[field].send(att)
130
+ value_in_db = value_in_db.to_i if att == :default && new_type == :integer && value_in_db.class == String
131
+ if att == :default && new_type == :boolean && value_in_db.class == String
132
+ value_in_db_to_i = value_in_db.to_i
133
+ value_in_db = false if value_in_db_to_i == 0
134
+ value_in_db = true if value_in_db_to_i == 1
135
+ end
136
+
137
+ if value != value_in_db
138
+ new_attr[att] = value
139
+ changed = true
140
+ end
141
+ end
142
+ end
143
+
144
+ # Change the column if applicable
145
+ change_column table_name, field, new_type, new_attr if changed
146
+ end
147
+ end
148
+ end
149
+
150
+ def auto_add_index(method, *args, &block)
151
+ table_name = args.shift.to_s
152
+ fields = Array(args.shift).map(&:to_s)
153
+ options = args.shift
154
+
155
+ index_name = options[:name] if options
156
+ index_name ||= ActiveRecord::Base.connection.index_name(table_name, :column => fields)
157
+
158
+ (self.indexes_in_schema ||= []) << index_name
159
+
160
+ unless ActiveRecord::Base.connection.indexes(table_name).detect { |i| i.name == index_name }
161
+ method_missing_without_auto_migration(method, *[table_name, fields, options], &block)
162
+ end
163
+ end
164
+
165
+ def drop_unused_tables
166
+ (ActiveRecord::Base.connection.tables - tables_in_schema - %w(schema_info schema_migrations)).each do |table|
167
+ drop_table table
168
+ end
169
+ end
170
+
171
+ def drop_unused_indexes
172
+ tables_in_schema.each do |table_name|
173
+ indexes_in_db = ActiveRecord::Base.connection.indexes(table_name).map(&:name)
174
+ (indexes_in_db - indexes_in_schema & indexes_in_db).each do |index_name|
175
+ remove_index table_name, :name => index_name
176
+ end
177
+ end
178
+ end
179
+
180
+ def update_schema_version(version)
181
+ if ActiveRecord::Base.connection.tables.include?("schema_migrations")
182
+ ActiveRecord::Base.connection.update("INSERT INTO schema_migrations VALUES ('#{version}')")
183
+ end
184
+ schema_file = File.join(Rails.root, "db", "schema.rb")
185
+ schema = File.read(schema_file)
186
+ schema.sub!(/:version => \d+/, ":version => #{version}")
187
+ File.open(schema_file, "w") { |f| f << schema }
188
+ end
189
+
190
+ end
191
+
192
+ end
193
+
194
+ ActiveRecord::Migration.send :include, AutoMigrations
@@ -0,0 +1,20 @@
1
+ namespace :db do
2
+ namespace :auto do
3
+ desc "Use schema.rb to auto-migrate"
4
+ task :migrate => :environment do
5
+ AutoMigrations.run
6
+ end
7
+ end
8
+
9
+ namespace :schema do
10
+ desc "Create migration from schema.rb"
11
+ task :to_migration => :environment do
12
+ AutoMigrations.schema_to_migration
13
+ end
14
+
15
+ desc "Create migration from schema.rb and reset migrations log"
16
+ task :to_migration_with_reset => :environment do
17
+ AutoMigrations.schema_to_migration(true)
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,8 @@
1
+ require 'test/unit'
2
+
3
+ class AutoMigrationsTest < Test::Unit::TestCase
4
+ # Replace this with your real tests.
5
+ def test_this_plugin
6
+ puts 'hello world'
7
+ end
8
+ end
metadata ADDED
@@ -0,0 +1,55 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: db_auto_migrations
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.1
5
+ platform: ruby
6
+ authors:
7
+ - sai (originally by PJ Hyett)
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2021-12-07 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: Auto database migration.
14
+ email: rubyer1993@gmail.com
15
+ executables:
16
+ - setup
17
+ extensions: []
18
+ extra_rdoc_files:
19
+ - LICENSE
20
+ - README
21
+ files:
22
+ - ".document"
23
+ - LICENSE
24
+ - README
25
+ - Rakefile
26
+ - VERSION
27
+ - bin/setup
28
+ - db_auto_migrations.gemspec
29
+ - init.rb
30
+ - lib/db_auto_migrations.rb
31
+ - lib/tasks/db_auto_migrations_tasks.rake
32
+ - test/db_auto_migrations_test.rb
33
+ homepage: https://github.com/sai1024/auto_migrations
34
+ licenses: []
35
+ metadata: {}
36
+ post_install_message:
37
+ rdoc_options: []
38
+ require_paths:
39
+ - lib
40
+ required_ruby_version: !ruby/object:Gem::Requirement
41
+ requirements:
42
+ - - ">="
43
+ - !ruby/object:Gem::Version
44
+ version: '0'
45
+ required_rubygems_version: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - ">="
48
+ - !ruby/object:Gem::Version
49
+ version: '0'
50
+ requirements: []
51
+ rubygems_version: 3.0.9
52
+ signing_key:
53
+ specification_version: 4
54
+ summary: Auto database migration.
55
+ test_files: []