Skip to content

Commit

Permalink
Merge pull request #9 from ka8725/schema-squasher
Browse files Browse the repository at this point in the history
Schema squasher
  • Loading branch information
ka8725 committed Nov 6, 2015
2 parents 63daa0d + 3e93fe5 commit f49de61
Show file tree
Hide file tree
Showing 12 changed files with 190 additions and 3 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,4 @@ spec/reports
test/tmp
test/version_tmp
tmp
test/rails_app/db/migrate
7 changes: 5 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,11 @@ describe CreateUsers do
end
```

The helper to load migrations `require_migration` is defined in the `migration_data/testing`. So you should to require it
to have access to this convinient require extension.
The helper to load migrations `require_migration` is defined in the `migration_data/testing`. So you should to require it to have access to this convinient require extension.

## Clean old migration

Once you are tired maintaining your old migrations you can clean up the old migrations. Use `rake db:migrate:squash` for this. The task will remove all old your migrations and will generate one migration with current database schema. You don't have to run migrations after this because the generated migration will have the latest database version.

## Contributing

Expand Down
3 changes: 3 additions & 0 deletions lib/migration_data.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,7 @@
require 'migration_data/version'
require 'migration_data/active_record/migration'

require 'rake'
import File.join(File.dirname(__FILE__), 'tasks', 'db.rake')

ActiveRecord::Migration.send(:include, MigrationData::ActiveRecord::Migration)
16 changes: 16 additions & 0 deletions lib/migration_data/active_record/schema_dumper.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
module MigrationData
module ActiveRecord
class SchemaDumper < ::ActiveRecord::SchemaDumper
def self.dump(connection=::ActiveRecord::Base.connection, stream=StringIO.new, config = ::ActiveRecord::Base)
new(connection, generate_options(config)).dump(stream)
stream
end

def dump(stream)
extensions(stream)
tables(stream)
stream
end
end
end
end
49 changes: 49 additions & 0 deletions lib/migration_data/squash.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
require 'migration_data/active_record/schema_dumper'

module MigrationData
class Squash
def call
remove_all_old_migrations
squash_schema
end

private

def squash_schema
File.open(migration_file_name, 'w') do |f|
content =
<<-MIGRATION.gsub(/^ {10}/, '')
class CreateSchema < ActiveRecord::Migration
def change
#{MigrationData::ActiveRecord::SchemaDumper.dump.string.strip.gsub(/^/, ' ')}
end
end
MIGRATION

f.write(content)
end
end

def remove_all_old_migrations
migration_dirs.each do |dir|
FileUtils.rm_rf(Dir.glob(File.join(dir, '**/*.rb')))
end
end

def current_version
::ActiveRecord::Migrator.current_version
end

def migration_dirs
::ActiveRecord::Tasks::DatabaseTasks.migrations_paths
end

def migration_dir
migration_dirs.first
end

def migration_file_name
File.join(migration_dir, "#{current_version}_create_schema.rb")
end
end
end
10 changes: 10 additions & 0 deletions lib/tasks/db.rake
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
require 'migration_data/squash'

namespace :db do
namespace :migrate do
desc 'Squashes all current migrations and dumps current schema to the latest one'
task :squash do
MigrationData::Squash.new.call
end
end
end
30 changes: 30 additions & 0 deletions test/rake_task_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
require 'test_helper'
require 'migration_data/squash'

describe 'db:schema:squash' do
let(:rake) { Rake::Application.new }

before do
CreateTableMigration.new.migrate(:up)
Rake.application = rake
Rake.application.rake_require('db', [File.expand_path('../../lib/tasks', __FILE__)])
end

describe '#invoke' do
it 'squashes the schema to the current migration' do
latest_migration = Rails.root.join('db', 'migrate', '0_create_schema.rb')
FileUtils.rm(latest_migration) if File.exist?(latest_migration)

Rake::Task['db:migrate:squash'].invoke
assert_equal <<-MIGRATION, File.read(latest_migration)
class CreateSchema < ActiveRecord::Migration
def change
create_table \"users\", force: :cascade do |t|
t.string \"name\"
end
end
end
MIGRATION
end
end
end
20 changes: 20 additions & 0 deletions test/schema_dumper_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
require 'test_helper'
require 'migration_data/active_record/schema_dumper'

describe MigrationData::ActiveRecord::SchemaDumper do
before do
CreateTableMigration.new.migrate(:up)
end

describe '#dump' do
it 'squashes the schema' do
stream = MigrationData::ActiveRecord::SchemaDumper.dump
assert_equal <<-SCHEMA, stream.string
create_table \"users\", force: :cascade do |t|
t.string \"name\"
end
SCHEMA
end
end
end
39 changes: 39 additions & 0 deletions test/squash_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
require 'test_helper'
require 'migration_data/squash'

describe MigrationData::Squash do
let(:squash) { MigrationData::Squash.new }
let(:db_path) { Rails.root.join('db', 'migrate') }

before do
CreateTableMigration.new.migrate(:up)
end

describe '#call' do
it 'squashes the schema to the current migration' do
squash.stub(:current_version, '100500') do
squash.call
end
assert_equal <<-MIGRATION, File.read(db_path.join('100500_create_schema.rb'))
class CreateSchema < ActiveRecord::Migration
def change
create_table \"users\", force: :cascade do |t|
t.string \"name\"
end
end
end
MIGRATION
end

it 'removes all the old migrations' do
old_migration = db_path.join('100500_old_migration.rb')
File.write(old_migration, '')

assert_equal true, File.exist?(old_migration)

squash.call

assert_equal false, File.exist?(old_migration)
end
end
end
7 changes: 7 additions & 0 deletions test/support/create_table_migration.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
class CreateTableMigration < ActiveRecord::Migration
def change
create_table :users, force: true do |t|
t.string :name
end
end
end
6 changes: 6 additions & 0 deletions test/support/rails_app.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
class RailsApp < Rails::Application
end

Rails.application.config.root = 'test/rails_app'

FileUtils.mkdir_p(Rails.application.config.root.join('db', 'migrate'))
5 changes: 4 additions & 1 deletion test/test_helper.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
require 'minitest/autorun'
require 'migration_data'
require 'rails'

ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database: 'tmp/test.sqlite3')
Dir[File.join(File.dirname(__FILE__), 'support', '**/*.rb')].each { |f| require f }

ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database: 'tmp/test.sqlite3')

0 comments on commit f49de61

Please sign in to comment.