blackbird 1.0.0.pre
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +8 -0
- data/CHANGELOG.md +9 -0
- data/Gemfile +6 -0
- data/LICENSE +19 -0
- data/README.md +77 -0
- data/ROADMAP.md +5 -0
- data/Rakefile +15 -0
- data/blackbird.gemspec +22 -0
- data/lib/blackbird.rb +39 -0
- data/lib/blackbird/column.rb +32 -0
- data/lib/blackbird/fragment.rb +58 -0
- data/lib/blackbird/helpers/join_tables.rb +50 -0
- data/lib/blackbird/helpers/typed_columns.rb +50 -0
- data/lib/blackbird/index.rb +29 -0
- data/lib/blackbird/migration.rb +218 -0
- data/lib/blackbird/patch.rb +64 -0
- data/lib/blackbird/processor_list.rb +41 -0
- data/lib/blackbird/processors/indexed_columns.rb +22 -0
- data/lib/blackbird/processors/normal_default.rb +7 -0
- data/lib/blackbird/railtie.rb +55 -0
- data/lib/blackbird/railtie/tasks.rake +8 -0
- data/lib/blackbird/schema.rb +25 -0
- data/lib/blackbird/schema/builder.rb +31 -0
- data/lib/blackbird/schema/changes.rb +77 -0
- data/lib/blackbird/schema/loader.rb +79 -0
- data/lib/blackbird/table.rb +71 -0
- data/lib/blackbird/table/builder.rb +124 -0
- data/lib/blackbird/table/changes.rb +86 -0
- data/lib/blackbird/transition.rb +85 -0
- data/lib/blackbird/version.rb +3 -0
- data/lib/rails/generators/active_record/transition/templates/fragment.rb +12 -0
- data/lib/rails/generators/active_record/transition/transition_generator.rb +25 -0
- data/spec/fixtures/a/comments_fragment.rb +10 -0
- data/spec/fixtures/a/pages_fragment.rb +9 -0
- data/spec/fixtures/a/posts_fragment.rb +9 -0
- data/spec/fixtures/a/users_fragment.rb +7 -0
- data/spec/fixtures/b/comments_fragment.rb +23 -0
- data/spec/fixtures/b/posts_fragment.rb +8 -0
- data/spec/spec.opts +4 -0
- data/spec/spec_helper.rb +72 -0
- data/spec/transitions/migration_spec.rb +116 -0
- data/spec/transitions/schema_loader_spec.rb +35 -0
- metadata +127 -0
data/.gitignore
ADDED
data/CHANGELOG.md
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
Copyright (c) 2010 Simon Menke
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
of this software and associated documentation files (the "Software"), to deal
|
5
|
+
in the Software without restriction, including without limitation the rights
|
6
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
copies of the Software, and to permit persons to whom the Software is
|
8
|
+
furnished to do so, subject to the following conditions:
|
9
|
+
|
10
|
+
The above copyright notice and this permission notice shall be included in
|
11
|
+
all copies or substantial portions of the Software.
|
12
|
+
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,77 @@
|
|
1
|
+
# Blackbird
|
2
|
+
|
3
|
+
Blackbird aims to remove traditional ActiveRecord migrations and replace it with DataMapper-like automatic migrations mixed with event based data patching.
|
4
|
+
|
5
|
+
The major advantage of Blackbird over migrations is that it allows Rails engines to define there own schemas which get automatically loaded in the application. The application remains in full control as it can overwrite an engines schema.
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
### Using Ruby gems
|
10
|
+
|
11
|
+
Add the gem to your `Gemfile`
|
12
|
+
|
13
|
+
gem "rails", "3.0.0.beta3"
|
14
|
+
gem "blackbird"
|
15
|
+
|
16
|
+
### Using git
|
17
|
+
|
18
|
+
Add the repo to your `Gemfile`
|
19
|
+
|
20
|
+
gem "blackbird", :git => "git://github.com/fd/blackbird.git"
|
21
|
+
|
22
|
+
## Quick Start Guide
|
23
|
+
|
24
|
+
Generate a `Post` model without the migration file.
|
25
|
+
|
26
|
+
$ rails g model Post --migration=false
|
27
|
+
|
28
|
+
Create a schema file at `app/schemas/posts_schema.rb` with the following contents:
|
29
|
+
|
30
|
+
class PostsSchema < Blackbird::Schema
|
31
|
+
|
32
|
+
table :posts do |t|
|
33
|
+
t.string :title
|
34
|
+
t.text :body
|
35
|
+
|
36
|
+
t.datetime :published_at
|
37
|
+
t.timestamps
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
Then transition the database to the new schema:
|
43
|
+
|
44
|
+
$ rake db:transition
|
45
|
+
--- Creating table posts
|
46
|
+
+c title:string
|
47
|
+
+c body:text
|
48
|
+
+c published_at:datetime
|
49
|
+
+c created_at:datetime
|
50
|
+
+c updated_at:datetime
|
51
|
+
|
52
|
+
Now, let's make some trivial changes:
|
53
|
+
|
54
|
+
- add an index to the published_at column
|
55
|
+
- add an extra column for the tags
|
56
|
+
|
57
|
+
and here is the diff:
|
58
|
+
|
59
|
+
--- a/app/schemas/posts_schema.rb
|
60
|
+
+++ b/app/schemas/posts_schema.rb
|
61
|
+
@@ -4,7 +4,9 @@ class PostsSchema < Blackbird::Schema
|
62
|
+
t.string :title
|
63
|
+
t.text :body
|
64
|
+
|
65
|
+
- t.datetime :published_at
|
66
|
+
+ t.string :tags
|
67
|
+
+
|
68
|
+
+ t.datetime :published_at, :index => true
|
69
|
+
t.timestamps
|
70
|
+
end
|
71
|
+
|
72
|
+
Transition the database to the updated schema:
|
73
|
+
|
74
|
+
$ rake db:transition
|
75
|
+
--- Constructive changes for posts
|
76
|
+
+c tags:string
|
77
|
+
+i published_at
|
data/ROADMAP.md
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'bundler'
|
2
|
+
Bundler::GemHelper.install_tasks
|
3
|
+
|
4
|
+
require 'spec/rake/spectask'
|
5
|
+
Spec::Rake::SpecTask.new(:spec) do |t|
|
6
|
+
t.spec_files = FileList['spec/**/*_spec.rb']
|
7
|
+
t.spec_opts = ['-O', 'spec/spec.opts']
|
8
|
+
end
|
9
|
+
|
10
|
+
require 'yard'
|
11
|
+
YARD::Rake::YardocTask.new do |t|
|
12
|
+
t.files = ['lib/**/*.rb']
|
13
|
+
end
|
14
|
+
|
15
|
+
task :default => :spec
|
data/blackbird.gemspec
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path("../lib/blackbird/version", __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |s|
|
5
|
+
s.name = "blackbird"
|
6
|
+
s.version = Blackbird::VERSION
|
7
|
+
s.platform = Gem::Platform::RUBY
|
8
|
+
s.authors = ["Simon Menke"]
|
9
|
+
s.email = ["simon.menke@gmail.com"]
|
10
|
+
s.homepage = "http://github.com/fd/blackbird"
|
11
|
+
s.summary = "Migrations should be more adaptable"
|
12
|
+
s.description = "Blackbird are Migrations but then better."
|
13
|
+
|
14
|
+
s.required_rubygems_version = ">= 1.3.6"
|
15
|
+
s.rubyforge_project = "blackbird"
|
16
|
+
|
17
|
+
s.add_runtime_dependency "activerecord", ">= 2.3.4"
|
18
|
+
|
19
|
+
s.files = `git ls-files`.split("\n")
|
20
|
+
s.executables = `git ls-files`.split("\n").map{|f| f =~ /^bin\/(.*)/ ? $1 : nil}.compact
|
21
|
+
s.require_path = 'lib'
|
22
|
+
end
|
data/lib/blackbird.rb
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
module Blackbird
|
2
|
+
|
3
|
+
require 'active_record'
|
4
|
+
|
5
|
+
require 'blackbird/version'
|
6
|
+
|
7
|
+
require 'blackbird/transition'
|
8
|
+
require 'blackbird/migration'
|
9
|
+
require 'blackbird/processor_list'
|
10
|
+
|
11
|
+
require 'blackbird/fragment'
|
12
|
+
require 'blackbird/schema'
|
13
|
+
require 'blackbird/table'
|
14
|
+
require 'blackbird/column'
|
15
|
+
require 'blackbird/index'
|
16
|
+
require 'blackbird/patch'
|
17
|
+
|
18
|
+
module Processors
|
19
|
+
require 'blackbird/processors/indexed_columns'
|
20
|
+
require 'blackbird/processors/normal_default'
|
21
|
+
end
|
22
|
+
|
23
|
+
module Helpers
|
24
|
+
require 'blackbird/helpers/typed_columns'
|
25
|
+
require 'blackbird/helpers/join_tables'
|
26
|
+
end
|
27
|
+
|
28
|
+
if defined? ::Rails::Railtie
|
29
|
+
require 'blackbird/railtie'
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.options
|
33
|
+
@options ||= {
|
34
|
+
:verbose => true,
|
35
|
+
:processors => Blackbird::ProcessorList.new
|
36
|
+
}
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
class Blackbird::Column
|
2
|
+
|
3
|
+
attr_reader :name, :type, :options
|
4
|
+
|
5
|
+
def initialize(name, type, options={})
|
6
|
+
options.delete(:default) if options[:default] == nil
|
7
|
+
@name, @type, @options = name.to_s, type, options
|
8
|
+
end
|
9
|
+
|
10
|
+
def process(visitor)
|
11
|
+
if visitor.respond_to?(:visit_column)
|
12
|
+
visitor.visit_column(self)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def primary?
|
17
|
+
!!@options[:primary]
|
18
|
+
end
|
19
|
+
|
20
|
+
def hash
|
21
|
+
[@name, @type, @options].hash
|
22
|
+
end
|
23
|
+
|
24
|
+
def change(type, options={})
|
25
|
+
@type, @options = type, options
|
26
|
+
end
|
27
|
+
|
28
|
+
def ==(other)
|
29
|
+
self.hash == other.hash
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
class Blackbird::Fragment
|
2
|
+
|
3
|
+
def self.subclasses
|
4
|
+
@subclasses ||= []
|
5
|
+
end
|
6
|
+
|
7
|
+
def self.inherited(subclass)
|
8
|
+
Blackbird::Fragment.subclasses.push(subclass)
|
9
|
+
subclass.extend InheritanceBlocker
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.instructions
|
13
|
+
@instructions ||= []
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.table(name, options={}, &block)
|
17
|
+
self.instructions << [:table, name, options, block]
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.patch(name, options={}, &block)
|
21
|
+
self.instructions << [:patch, name, options, block]
|
22
|
+
end
|
23
|
+
|
24
|
+
def initialize
|
25
|
+
@instructions = self.class.instructions.dup
|
26
|
+
end
|
27
|
+
|
28
|
+
def apply(builder)
|
29
|
+
@instructions.each do |instruction|
|
30
|
+
instruction = instruction.dup
|
31
|
+
instruction[1,0] = self
|
32
|
+
block = (Proc === instruction.last ? instruction.pop : nil)
|
33
|
+
builder.__send__(*instruction, &block)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def connection
|
40
|
+
ActiveRecord::Base.connection
|
41
|
+
end
|
42
|
+
|
43
|
+
%w( select_values select_value select_rows select_all execute ).each do |m|
|
44
|
+
define_method(m) do |sql_pattern, *args|
|
45
|
+
sql = sql = sql_pattern.gsub('?') do
|
46
|
+
connection.quote(arguments.shift)
|
47
|
+
end
|
48
|
+
connection.__send__(m, sql)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
module InheritanceBlocker
|
53
|
+
def inherited(base)
|
54
|
+
raise "#{base} cannot inherit from non abstract fragment #{self}"
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module Blackbird::Helpers::JoinTables
|
2
|
+
|
3
|
+
def join(*args, &block)
|
4
|
+
|
5
|
+
tables = []
|
6
|
+
columns = []
|
7
|
+
|
8
|
+
while arg = args.shift
|
9
|
+
case arg
|
10
|
+
when String, Symbol
|
11
|
+
tables << arg.to_s
|
12
|
+
columns << "#{arg.to_s.singularize}_id"
|
13
|
+
|
14
|
+
when Array
|
15
|
+
tables << arg[0].to_s
|
16
|
+
columns << arg[1].to_s
|
17
|
+
|
18
|
+
when Hash
|
19
|
+
args = arg.to_ary + args
|
20
|
+
|
21
|
+
else
|
22
|
+
raise ArgumentError
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
name = tables.dup.sort.join('_')
|
28
|
+
|
29
|
+
table name, :id => false do |t|
|
30
|
+
|
31
|
+
columns.each do |column|
|
32
|
+
t.integer column
|
33
|
+
end
|
34
|
+
|
35
|
+
if block
|
36
|
+
if block.arity == 1
|
37
|
+
block.call(t)
|
38
|
+
else
|
39
|
+
t.instance_eval(&block)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
self
|
46
|
+
end
|
47
|
+
|
48
|
+
Blackbird::Schema::Builder.send(:include, self)
|
49
|
+
|
50
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module Blackbird::Helpers::TypedColumns
|
2
|
+
|
3
|
+
def integer(name, options={})
|
4
|
+
column(name, :integer, options)
|
5
|
+
end
|
6
|
+
|
7
|
+
def float(name, options={})
|
8
|
+
column(name, :float, options)
|
9
|
+
end
|
10
|
+
|
11
|
+
def decimal(name, options={})
|
12
|
+
column(name, :decimal, options)
|
13
|
+
end
|
14
|
+
|
15
|
+
def string(name, options={})
|
16
|
+
column(name, :string, options)
|
17
|
+
end
|
18
|
+
|
19
|
+
def text(name, options={})
|
20
|
+
column(name, :text, options)
|
21
|
+
end
|
22
|
+
|
23
|
+
def boolean(name, options={})
|
24
|
+
column(name, :boolean, options)
|
25
|
+
end
|
26
|
+
|
27
|
+
def binary(name, options={})
|
28
|
+
column(name, :binary, options)
|
29
|
+
end
|
30
|
+
|
31
|
+
def datetime(name, options={})
|
32
|
+
column(name, :datetime, options)
|
33
|
+
end
|
34
|
+
|
35
|
+
def date(name, options={})
|
36
|
+
column(name, :date, options)
|
37
|
+
end
|
38
|
+
|
39
|
+
def timestamp(name, options={})
|
40
|
+
column(name, :timestamp, options)
|
41
|
+
end
|
42
|
+
|
43
|
+
def timestamps
|
44
|
+
datetime :created_at
|
45
|
+
datetime :updated_at
|
46
|
+
end
|
47
|
+
|
48
|
+
Blackbird::Table::Builder.send(:include, self)
|
49
|
+
|
50
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
class Blackbird::Index
|
2
|
+
|
3
|
+
attr_reader :name, :columns, :options
|
4
|
+
|
5
|
+
def initialize(table_name, columns, options={})
|
6
|
+
@table_name = table_name
|
7
|
+
@columns, @options = [columns].flatten.compact, options
|
8
|
+
@columns.collect! { |n| n.to_s }
|
9
|
+
end
|
10
|
+
|
11
|
+
def process(visitor)
|
12
|
+
if visitor.respond_to?(:visit_index)
|
13
|
+
visitor.visit_index(self)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def name
|
18
|
+
@options[:name] ||= "index_#{@table_name}_on_#{Array(@columns) * '_and_'}"
|
19
|
+
end
|
20
|
+
|
21
|
+
def hash
|
22
|
+
[@columns, @options].hash
|
23
|
+
end
|
24
|
+
|
25
|
+
def ==(other)
|
26
|
+
self.hash == other.hash
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
@@ -0,0 +1,218 @@
|
|
1
|
+
# Blackbird::Migration is responsible for creating database instructions
|
2
|
+
class Blackbird::Migration
|
3
|
+
|
4
|
+
attr_reader :instructions
|
5
|
+
|
6
|
+
def self.build(current, future, changes)
|
7
|
+
new(current, future, changes).build
|
8
|
+
end
|
9
|
+
|
10
|
+
def initialize(current, future, changes)
|
11
|
+
@current, @future, @changes = current, future, changes
|
12
|
+
@instructions = []
|
13
|
+
end
|
14
|
+
|
15
|
+
def build
|
16
|
+
evaluate_patches
|
17
|
+
|
18
|
+
remove_old_indexes
|
19
|
+
|
20
|
+
create_new_tables
|
21
|
+
change_existing_tables
|
22
|
+
remove_old_tables
|
23
|
+
|
24
|
+
create_new_indexes
|
25
|
+
|
26
|
+
self
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def create_new_tables
|
32
|
+
@changes.new_tables.each do |table_name|
|
33
|
+
table = @future.tables[table_name]
|
34
|
+
|
35
|
+
pk_name = table.primary_key
|
36
|
+
has_pk = !!pk_name
|
37
|
+
|
38
|
+
log "--- Creating table #{table_name}"
|
39
|
+
run :create_table, table_name, table.options.merge(:id => has_pk, :primary_key => pk_name)
|
40
|
+
|
41
|
+
table.columns.each do |name, column|
|
42
|
+
next if name == pk_name
|
43
|
+
|
44
|
+
log " +c #{name}:#{column.type}"
|
45
|
+
run :add_column, table_name, name, column.type, column.options
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def evaluate_patches
|
51
|
+
@evaluated_patches = []
|
52
|
+
@changes.new_patches.each do |patch_name|
|
53
|
+
|
54
|
+
patch = @future.patches[patch_name]
|
55
|
+
patch.call(@changes)
|
56
|
+
@evaluated_patches << patch
|
57
|
+
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def apply_patches
|
62
|
+
@evaluated_patches.each do |patch|
|
63
|
+
|
64
|
+
log "--- Applying patch #{patch.name}"
|
65
|
+
@instructions.concat(patch.instructions)
|
66
|
+
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def change_existing_tables
|
71
|
+
# new columns
|
72
|
+
@changes.changed_tables.each do |table_name|
|
73
|
+
changes = @changes.table(table_name)
|
74
|
+
future_table = @future.tables[table_name]
|
75
|
+
|
76
|
+
unless changes.new_columns.empty?
|
77
|
+
log "--- Constructive changes for #{table_name}"
|
78
|
+
end
|
79
|
+
|
80
|
+
changes.new_columns.each do |name|
|
81
|
+
column = future_table.columns[name]
|
82
|
+
|
83
|
+
log " +c #{name}:#{column.type}"
|
84
|
+
run :add_column, table_name, name, column.type, column.options
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
apply_patches
|
89
|
+
|
90
|
+
# column changes
|
91
|
+
@changes.changed_tables.each do |table_name|
|
92
|
+
changes = @changes.table(table_name)
|
93
|
+
current_table = @current.tables[table_name]
|
94
|
+
future_table = @future.tables[table_name]
|
95
|
+
|
96
|
+
unless changes.changed_columns.empty?
|
97
|
+
log "--- Mutative changes for #{table_name}"
|
98
|
+
end
|
99
|
+
|
100
|
+
changes.changed_columns.each do |name|
|
101
|
+
column = future_table.columns[name]
|
102
|
+
|
103
|
+
log " ~c #{name}:#{column.type} #{current_table.columns[name].options.inspect} => #{column.options.inspect}"
|
104
|
+
run :change_column, table_name, name, column.type, column.options
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
# old columns
|
109
|
+
@changes.changed_tables.each do |table_name|
|
110
|
+
changes = @changes.table(table_name)
|
111
|
+
current_table = @current.tables[table_name]
|
112
|
+
|
113
|
+
unless changes.old_columns.empty?
|
114
|
+
log "--- Destructive changes for #{table_name}"
|
115
|
+
end
|
116
|
+
|
117
|
+
changes.old_columns.each do |name|
|
118
|
+
column = current_table.columns[name]
|
119
|
+
|
120
|
+
log " -c #{name}:#{column.type}"
|
121
|
+
run :remove_column, table_name, name
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
def remove_old_tables
|
127
|
+
@changes.old_tables.each do |table_name|
|
128
|
+
log "-- Dropping table #{table_name}"
|
129
|
+
run :drop_table, table_name
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
def remove_old_indexes
|
134
|
+
@changes.changed_tables.each do |table_name|
|
135
|
+
changes = @changes.table(table_name)
|
136
|
+
current_table = @current.tables[table_name]
|
137
|
+
|
138
|
+
changes.old_indexes.each do |name|
|
139
|
+
index = current_table.indexes[name]
|
140
|
+
|
141
|
+
log(index.options[:unique] ?
|
142
|
+
" -u #{index.columns * ' '}" :
|
143
|
+
" -i #{index.columns * ' '}" )
|
144
|
+
run :remove_index, table_name, {:name => name}
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
@changes.changed_tables.each do |table_name|
|
149
|
+
changes = @changes.table(table_name)
|
150
|
+
future_table = @future.tables[table_name]
|
151
|
+
|
152
|
+
changes.changed_indexes.each do |name|
|
153
|
+
index = future_table.indexes[name]
|
154
|
+
|
155
|
+
log(index.options[:unique] ?
|
156
|
+
" ~u #{index.columns * ' '}" :
|
157
|
+
" ~i #{index.columns * ' '}" )
|
158
|
+
|
159
|
+
run :remove_index, table_name, {:name => name}
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
def create_new_indexes
|
165
|
+
@changes.changed_tables.each do |table_name|
|
166
|
+
changes = @changes.table(table_name)
|
167
|
+
future_table = @future.tables[table_name]
|
168
|
+
|
169
|
+
changes.changed_indexes.each do |name|
|
170
|
+
index = future_table.indexes[name]
|
171
|
+
|
172
|
+
log(index.options[:unique] ?
|
173
|
+
" ~u #{index.columns * ' '}" :
|
174
|
+
" ~i #{index.columns * ' '}" )
|
175
|
+
|
176
|
+
run :add_index, table_name, index.columns, index.options
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
@changes.changed_tables.each do |table_name|
|
181
|
+
changes = @changes.table(table_name)
|
182
|
+
future_table = @future.tables[table_name]
|
183
|
+
|
184
|
+
changes.new_indexes.each do |name|
|
185
|
+
index = future_table.indexes[name]
|
186
|
+
|
187
|
+
log(index.options[:unique] ?
|
188
|
+
" +u #{index.columns * ' '}" :
|
189
|
+
" +i #{index.columns * ' '}" )
|
190
|
+
|
191
|
+
run :add_index, table_name, index.columns, index.options
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
@changes.new_tables.each do |table_name|
|
196
|
+
table = @future.tables[table_name]
|
197
|
+
|
198
|
+
table.indexes.each do |name, index|
|
199
|
+
log(index.options[:unique] ?
|
200
|
+
" +u #{index.columns * ' '}" :
|
201
|
+
" +i #{index.columns * ' '}" )
|
202
|
+
|
203
|
+
run :add_index, table_name, index.columns, index.options
|
204
|
+
end
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
def run(*instruction)
|
209
|
+
@instructions << instruction
|
210
|
+
end
|
211
|
+
|
212
|
+
def log(message)
|
213
|
+
if Blackbird.options[:verbose]
|
214
|
+
run :log, message
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
end
|