sequel_migration_builder 0.1.4 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG ADDED
@@ -0,0 +1,9 @@
1
+ CHANGELOG
2
+
3
+ == 0.2.0
4
+
5
+ * Switched to using the new style 'change' block in the generated
6
+ migrations, rather than 'up' or 'down'. This bumps the Sequel
7
+ requirement to at least 3.18.0.
8
+ * Changes in indexes are properly handled - not just if the names
9
+ are different.
data/README.rdoc CHANGED
@@ -3,6 +3,16 @@
3
3
  Builds sequel migrations based on the differences between an abstract
4
4
  representation of the desired schema and a database instance.
5
5
 
6
+ This is quite a low-level library - it doesn't provide any functionality
7
+ to write out migration files, nor does it provide a ruby DSL for defining
8
+ your schema (see Schema format below).
9
+
10
+ This library is also very, very new, so there WILL be bugs.
11
+
12
+ == Install
13
+
14
+ sudo gem install sequel_migration_builder
15
+
6
16
  == Example
7
17
 
8
18
  require 'sequel/migration_builder'
@@ -38,7 +48,7 @@ as a hash. A sample YAML version might look like:
38
48
 
39
49
  == Requirements
40
50
 
41
- * Sequel 3.12.0 or higher
51
+ * Sequel 3.18.0 or higher
42
52
 
43
53
  == TODO
44
54
 
data/Rakefile CHANGED
@@ -10,7 +10,7 @@ begin
10
10
  gem.email = "roland.swingler@gmail.com"
11
11
  gem.homepage = "http://github.com/knaveofdiamonds/sequel_migration_builder"
12
12
  gem.authors = ["Roland Swingler"]
13
- gem.add_dependency "sequel", ">= 3.12.0"
13
+ gem.add_dependency "sequel", ">= 3.18.0"
14
14
  gem.add_development_dependency "rspec", ">= 1.2.9"
15
15
  # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
16
16
  end
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.4
1
+ 0.2.0
@@ -1,5 +1,6 @@
1
1
  require 'sequel/extensions/blank'
2
2
  require 'sequel/schema/db_column'
3
+ require 'sequel/schema/db_index'
3
4
  require 'sequel/schema/db_schema_parser'
4
5
  require 'sequel/schema/alter_table_operations'
5
6
 
@@ -30,38 +31,23 @@ module Sequel
30
31
 
31
32
  add_line "Sequel.migration do"
32
33
  indent do
33
- generate_up(tables)
34
- generate_down(tables)
34
+ generate_migration_body(tables)
35
35
  end
36
36
  add_line "end\n"
37
37
 
38
38
  result.join("\n")
39
39
  end
40
40
 
41
- # Generates the 'up' part of the migration.
41
+ # Generates the 'change' block of the migration.
42
42
  #
43
- def generate_up(tables)
43
+ def generate_migration_body(tables)
44
44
  current_tables, new_tables = table_names(tables).partition do |table_name|
45
45
  @db_table_names.include?(table_name)
46
46
  end
47
47
 
48
- add_line "up do"
48
+ add_line "change do"
49
49
  create_new_tables(new_tables, tables)
50
- alter_tables(current_tables, tables, :up)
51
- add_line "end"
52
- add_blank_line
53
- end
54
-
55
- # Generates the down part of the migration.
56
- #
57
- def generate_down(tables)
58
- current_tables, new_tables = table_names(tables).partition do |table_name|
59
- @db_table_names.include?(table_name)
60
- end
61
-
62
- add_line "down do"
63
- alter_tables(current_tables, tables, :down)
64
- drop_new_tables(new_tables)
50
+ alter_tables(current_tables, tables)
65
51
  add_line "end"
66
52
  end
67
53
 
@@ -84,13 +70,13 @@ module Sequel
84
70
 
85
71
  # Generates any alter table statements for current tables.
86
72
  #
87
- def alter_tables(current_table_names, tables, direction)
73
+ def alter_tables(current_table_names, tables)
88
74
  each_table(current_table_names, tables) do |table_name, table, last_table|
89
75
  hsh = table.dup
90
76
  hsh[:columns] = hsh[:columns].map {|c| Schema::DbColumn.build_from_hash(c) }
91
77
  operations = Schema::AlterTableOperations.build(@db_tables[table_name], hsh)
92
78
  unless operations.empty?
93
- alter_table_statement table_name, operations, direction
79
+ alter_table_statement table_name, operations
94
80
  add_blank_line unless last_table
95
81
  end
96
82
  end
@@ -98,10 +84,10 @@ module Sequel
98
84
 
99
85
  # Generates an individual alter table statement.
100
86
  #
101
- def alter_table_statement(table_name, operations, direction)
87
+ def alter_table_statement(table_name, operations)
102
88
  add_line "alter_table #{table_name.inspect} do"
103
89
  indent do
104
- operations.map {|op| op.__send__(direction) }.compact.each {|op| add_line op }
90
+ operations.compact.each {|op| add_line op }
105
91
  end
106
92
  add_line "end"
107
93
  end
@@ -109,30 +95,44 @@ module Sequel
109
95
  # Generates an individual create_table statement.
110
96
  #
111
97
  def create_table_statement(table_name, table)
98
+ normalize_primary_key(table)
112
99
  add_line "create_table #{table_name.inspect}#{pretty_hash(table[:table_options])} do"
113
100
  indent do
114
- table[:primary_key] = [table[:primary_key]] if table[:primary_key].kind_of?(Symbol)
115
- table[:columns].each do |c|
116
- column = Schema::DbColumn.build_from_hash(c)
117
- if table[:primary_key] && table[:primary_key].size == 1 && table[:primary_key].first == column.name
118
- column.single_primary_key = true
119
- end
120
- add_line column.define_statement
121
- end
122
- if table[:indexes]
123
- add_blank_line
124
- table[:indexes].each do |name, options|
125
- opts = options.clone
126
- columns = opts.delete(:columns)
127
- add_line "index #{columns.inspect}, :name => #{name.to_sym.inspect}#{pretty_hash(opts)}"
128
- end
101
+ output_columns(table[:columns], table[:primary_key])
102
+ output_indexes(table[:indexes])
103
+ output_composite_primary_key(table[:primary_key])
104
+ end
105
+ add_line "end"
106
+ end
107
+
108
+ def normalize_primary_key(table)
109
+ table[:primary_key] = [table[:primary_key]] if table[:primary_key].kind_of?(Symbol)
110
+ end
111
+
112
+ def output_columns(columns, primary_key)
113
+ columns.each do |c|
114
+ column = Schema::DbColumn.build_from_hash(c)
115
+ if primary_key && primary_key.size == 1 && primary_key.first == column.name
116
+ column.single_primary_key = true
129
117
  end
130
- if table[:primary_key] && table[:primary_key].size > 1
131
- add_blank_line
132
- add_line "primary_key #{table[:primary_key].inspect}"
118
+ add_line column.define_statement
119
+ end
120
+ end
121
+
122
+ def output_indexes(indexes)
123
+ if indexes
124
+ add_blank_line
125
+ Schema::DbIndex.build_from_hash(indexes).each do |idx|
126
+ add_line idx.define_statement
133
127
  end
134
128
  end
135
- add_line "end"
129
+ end
130
+
131
+ def output_composite_primary_key(primary_key)
132
+ if primary_key && primary_key.size > 1
133
+ add_blank_line
134
+ add_line "primary_key #{primary_key.inspect}"
135
+ end
136
136
  end
137
137
 
138
138
  private
@@ -1,60 +1,48 @@
1
1
  module Sequel
2
2
  module Schema
3
- module AlterTableOperations
4
-
3
+ class AlterTableOperations
5
4
  # Returns an array of operations to change the current database
6
5
  # table to be like the defined table.
7
6
  #
8
7
  def self.build(db_table, new_table)
8
+ new.build(db_table, new_table)
9
+ end
10
+
11
+ def build(db_table, new_table)
9
12
  db_columns = db_table[:columns].inject({}) {|hsh, column| hsh[column.name] = column; hsh }
13
+ new_column_names = new_table[:columns].map {|c| c.name }
14
+ dropped_columns = db_columns.keys - new_column_names
10
15
 
11
16
  operations = new_table[:columns].map do |column|
12
17
  if db_columns[column.name]
13
18
  build_column_operations db_columns[column.name], column
14
19
  else
15
- AddColumn.new(column)
20
+ column.add_statement
16
21
  end
17
22
  end.flatten
18
23
 
19
- new_column_names = new_table[:columns].map {|c| c.name }
20
- dropped_columns = db_columns.keys - new_column_names
21
-
22
24
  operations += dropped_columns.map do |name|
23
- DropColumn.new(db_columns[name])
25
+ db_columns[name].drop_statement
24
26
  end
25
27
 
26
- db_indexes = db_table[:indexes] || {}
27
- new_indexes = new_table[:indexes] || {}
28
-
29
- operations += (db_indexes.keys - new_indexes.keys).map do |index_name|
30
- dropped_column = db_indexes[index_name][:columns].size == 1 && dropped_columns.include?(db_indexes[index_name][:columns].first)
31
-
32
- DropIndex.new(index_name,
33
- db_indexes[index_name][:columns],
34
- db_indexes[index_name][:unique],
35
- ! dropped_column)
28
+ db_indexes = Schema::DbIndex.build_from_hash(db_table[:indexes] || {})
29
+ new_indexes = Schema::DbIndex.build_from_hash(new_table[:indexes] || {})
30
+
31
+ operations += (db_indexes - new_indexes).map do |index|
32
+ index.drop_statement unless index.columns.all? {|c| dropped_columns.include?(c) }
36
33
  end
37
-
38
- operations += (new_indexes.keys - db_indexes.keys).map do |index_name|
39
- if new_indexes[index_name][:columns].kind_of?(Symbol)
40
- dropped_column = dropped_columns.include?(new_indexes[index_name][:columns])
41
- else
42
- dropped_column = new_indexes[index_name][:columns].size == 1 && dropped_columns.include?(new_indexes[index_name][:columns].first)
43
- end
44
-
45
- AddIndex.new(index_name,
46
- new_indexes[index_name][:columns],
47
- new_indexes[index_name][:unique],
48
- ! dropped_column)
34
+
35
+ operations += (new_indexes - db_indexes).map do |index|
36
+ index.add_statement
49
37
  end
50
-
51
- operations
38
+
39
+ operations
52
40
  end
53
41
 
54
42
  # Returns an array of operations to change the current database
55
43
  # column to be like the defined column.
56
44
  #
57
- def self.build_column_operations(db_column, new_column)
45
+ def build_column_operations(db_column, new_column)
58
46
  result = []
59
47
 
60
48
  diffs = db_column.diff(new_column)
@@ -63,63 +51,7 @@ module Sequel
63
51
  result << :change_default_statement if diffs.include?(:default) && result.empty?
64
52
  result << :change_null_statement if diffs.include?(:null)
65
53
 
66
- result.map {|k| ChangeColumn.new(db_column, new_column, k) }
67
- end
68
-
69
- # Base alter table operation class. Each operation will return
70
- # Sequel::Migration statement(s) to alter the table.
71
- class Operation
72
- # Returns the statement for the up part of the migration
73
- attr_reader :up
74
-
75
- # Returns the statement for the down part of the operation
76
- attr_reader :down
77
- end
78
-
79
- # Changes a column.
80
- class ChangeColumn < Operation
81
- def initialize(old_column, new_column, statement)
82
- @up = new_column.__send__(statement)
83
- @down = old_column.__send__(statement)
84
- end
85
- end
86
-
87
- # Adds a column.
88
- class AddColumn < Operation
89
- def initialize(column)
90
- @up = column.add_statement
91
- @down = column.drop_statement
92
- end
93
- end
94
-
95
- # Drops a column.
96
- class DropColumn < Operation
97
- def initialize(column)
98
- @up = column.drop_statement
99
- @down = column.add_statement
100
- end
101
- end
102
-
103
- # Adds an index.
104
- class AddIndex < Operation
105
- def initialize(name, columns, unique, include_drop_index=true)
106
- @up = "add_index #{columns.inspect}, :name => #{name.inspect}"
107
- @up << ", :unique => true" if unique
108
- if include_drop_index
109
- @down = "drop_index #{columns.inspect}, :name => #{name.inspect}"
110
- end
111
- end
112
- end
113
-
114
- # Drops an index.
115
- class DropIndex < Operation
116
- def initialize(name, columns, unique, include_drop_index=true)
117
- if include_drop_index
118
- @up = "drop_index #{columns.inspect}, :name => #{name.inspect}"
119
- end
120
- @down = "add_index #{columns.inspect}, :name => #{name.inspect}"
121
- @down << ", :unique => true" if unique
122
- end
54
+ result.map {|statement| new_column.__send__(statement) }
123
55
  end
124
56
  end
125
57
  end
@@ -0,0 +1,78 @@
1
+ module Sequel
2
+ module Schema
3
+ class DbIndex
4
+ attr_accessor :name
5
+ attr_reader :columns
6
+
7
+ # Builds an Array of DbIndexes from the index hash returned by
8
+ # Sequel::Database#indexes
9
+ def self.build_from_hash(definitions)
10
+ definitions.map {|name,attrs| new(name, attrs[:columns], attrs[:unique]) }
11
+ end
12
+
13
+ # Creates a new DbIndex definition.
14
+ #
15
+ # columns may be a single column name as a symbol, or an array
16
+ # of column symbol names.
17
+ #
18
+ # Indexes are not unique by default.
19
+ def initialize(name, columns, unique=false)
20
+ @name = name.to_sym
21
+ @columns = columns.kind_of?(Array) ? columns.clone : [columns]
22
+ @unique = unique
23
+ end
24
+
25
+ # Returns true if this index is unique
26
+ def unique?
27
+ !! @unique
28
+ end
29
+
30
+ # Returns true if this index has more than one column.
31
+ def multi_column?
32
+ @columns.size > 1
33
+ end
34
+
35
+ # Returns the sequel migration statement to define an index in a
36
+ # create_table block.
37
+ def define_statement
38
+ base_add_statement('index')
39
+ end
40
+
41
+ # Returns the sequel migration statement to add an index in an
42
+ # alter_table block.
43
+ def add_statement
44
+ base_add_statement('add_index')
45
+ end
46
+
47
+ # Returns the sequel migration statement to remove an index in an
48
+ # alter_table block.
49
+ def drop_statement
50
+ "drop_index #{columns_for_statement.inspect}, :name => #{name.inspect}"
51
+ end
52
+
53
+ # Indexes are equal if all their attributes are equal.
54
+ def ==(other)
55
+ other.kind_of?(self.class) &&
56
+ @name == other.name && @columns == other.columns && @unique == other.unique?
57
+ end
58
+ alias :eql? :==
59
+
60
+ def hash # :nodoc:
61
+ @name.hash
62
+ end
63
+
64
+ private
65
+
66
+ def columns_for_statement
67
+ return columns.first unless multi_column?
68
+ columns
69
+ end
70
+
71
+ def base_add_statement(keyword)
72
+ parts = ["#{keyword} #{columns_for_statement.inspect}, :name => #{name.inspect}"]
73
+ parts << ":unique => #{@unique.inspect}" if unique?
74
+ parts.join(", ")
75
+ end
76
+ end
77
+ end
78
+ end
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{sequel_migration_builder}
8
- s.version = "0.1.4"
8
+ s.version = "0.2.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Roland Swingler"]
12
- s.date = %q{2010-08-13}
12
+ s.date = %q{2011-01-13}
13
13
  s.description = %q{Build Sequel Migrations based on the differences between two schemas}
14
14
  s.email = %q{roland.swingler@gmail.com}
15
15
  s.extra_rdoc_files = [
@@ -19,6 +19,7 @@ Gem::Specification.new do |s|
19
19
  s.files = [
20
20
  ".document",
21
21
  ".gitignore",
22
+ "CHANGELOG",
22
23
  "LICENSE",
23
24
  "README.rdoc",
24
25
  "Rakefile",
@@ -26,10 +27,12 @@ Gem::Specification.new do |s|
26
27
  "lib/sequel/migration_builder.rb",
27
28
  "lib/sequel/schema/alter_table_operations.rb",
28
29
  "lib/sequel/schema/db_column.rb",
30
+ "lib/sequel/schema/db_index.rb",
29
31
  "lib/sequel/schema/db_schema_parser.rb",
30
32
  "sequel_migration_builder.gemspec",
31
33
  "spec/alter_table_operations_spec.rb",
32
34
  "spec/db_column_spec.rb",
35
+ "spec/db_index_spec.rb",
33
36
  "spec/db_schema_parser_spec.rb",
34
37
  "spec/migration_builder_spec.rb",
35
38
  "spec/spec.opts",
@@ -38,11 +41,12 @@ Gem::Specification.new do |s|
38
41
  s.homepage = %q{http://github.com/knaveofdiamonds/sequel_migration_builder}
39
42
  s.rdoc_options = ["--charset=UTF-8"]
40
43
  s.require_paths = ["lib"]
41
- s.rubygems_version = %q{1.3.6}
44
+ s.rubygems_version = %q{1.3.7}
42
45
  s.summary = %q{Build Sequel Migrations based on the differences between two schemas}
43
46
  s.test_files = [
44
47
  "spec/alter_table_operations_spec.rb",
45
48
  "spec/db_column_spec.rb",
49
+ "spec/db_index_spec.rb",
46
50
  "spec/db_schema_parser_spec.rb",
47
51
  "spec/migration_builder_spec.rb",
48
52
  "spec/spec_helper.rb"
@@ -52,15 +56,15 @@ Gem::Specification.new do |s|
52
56
  current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
53
57
  s.specification_version = 3
54
58
 
55
- if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
56
- s.add_runtime_dependency(%q<sequel>, [">= 3.12.0"])
59
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
60
+ s.add_runtime_dependency(%q<sequel>, [">= 3.18.0"])
57
61
  s.add_development_dependency(%q<rspec>, [">= 1.2.9"])
58
62
  else
59
- s.add_dependency(%q<sequel>, [">= 3.12.0"])
63
+ s.add_dependency(%q<sequel>, [">= 3.18.0"])
60
64
  s.add_dependency(%q<rspec>, [">= 1.2.9"])
61
65
  end
62
66
  else
63
- s.add_dependency(%q<sequel>, [">= 3.12.0"])
67
+ s.add_dependency(%q<sequel>, [">= 3.18.0"])
64
68
  s.add_dependency(%q<rspec>, [">= 1.2.9"])
65
69
  end
66
70
  end
@@ -4,69 +4,73 @@ def build_column(hash)
4
4
  Sequel::Schema::DbColumn.build_from_hash(hash)
5
5
  end
6
6
 
7
- describe "Sequel::Schema::AlterTableOperations.build_column_operations" do
7
+ describe "Sequel::Schema::AlterTableOperations#build_column_operations" do
8
+ before :each do
9
+ @subject = Sequel::Schema::AlterTableOperations.new
10
+ end
11
+
8
12
  it "should return an empty Array if there are no differences between column definitions" do
9
13
  a = build_column(:name => :foo, :column_type => :integer)
10
14
  b = build_column(:name => :foo, :column_type => :integer)
11
15
 
12
- Sequel::Schema::AlterTableOperations.build_column_operations(a,b).should == []
16
+ @subject.build_column_operations(a,b).should == []
13
17
  end
14
18
 
15
19
  it "should return a ChangeColumn operation if the types are different" do
16
20
  a = build_column(:name => :foo, :column_type => :integer)
17
21
  b = build_column(:name => :foo, :column_type => :smallint)
18
- ops = Sequel::Schema::AlterTableOperations.build_column_operations(a,b)
22
+ ops = @subject.build_column_operations(a,b)
19
23
 
20
- ops.first.up.should == "set_column_type :foo, :smallint, :default => nil"
24
+ ops.first.should == "set_column_type :foo, :smallint, :default => nil"
21
25
  end
22
26
 
23
27
  it "should return a ChangeColumn operation if the sizes are different" do
24
28
  a = build_column(:name => :foo, :column_type => :char, :size => 20)
25
29
  b = build_column(:name => :foo, :column_type => :char, :size => 10)
26
- ops = Sequel::Schema::AlterTableOperations.build_column_operations(a,b)
30
+ ops = @subject.build_column_operations(a,b)
27
31
 
28
- ops.first.up.should == "set_column_type :foo, :char, :default => nil, :size => 10"
32
+ ops.first.should == "set_column_type :foo, :char, :default => nil, :size => 10"
29
33
  end
30
34
 
31
35
  it "should return a ChangeColumn operation if the unsigned value is different" do
32
36
  a = build_column(:name => :foo, :column_type => :integer, :unsigned => true)
33
37
  b = build_column(:name => :foo, :column_type => :integer, :unsigned => false)
34
- ops = Sequel::Schema::AlterTableOperations.build_column_operations(a,b)
38
+ ops = @subject.build_column_operations(a,b)
35
39
 
36
- ops.first.up.should == "set_column_type :foo, :integer, :default => nil, :unsigned => false"
40
+ ops.first.should == "set_column_type :foo, :integer, :default => nil, :unsigned => false"
37
41
  end
38
42
 
39
43
  it "should return a ChangeColumn operation to set the null value if the null value is different" do
40
44
  a = build_column(:name => :foo, :column_type => :integer, :null => true)
41
45
  b = build_column(:name => :foo, :column_type => :integer, :null => false)
42
- ops = Sequel::Schema::AlterTableOperations.build_column_operations(a,b)
46
+ ops = @subject.build_column_operations(a,b)
43
47
 
44
- ops.first.up.should == "set_column_allow_null :foo, false"
48
+ ops.first.should == "set_column_allow_null :foo, false"
45
49
  end
46
50
 
47
51
  it "should return a ChangeColumn operation to set the default if the default value is different" do
48
52
  a = build_column(:name => :foo, :column_type => :integer, :default => 1)
49
53
  b = build_column(:name => :foo, :column_type => :integer, :default => 2)
50
- ops = Sequel::Schema::AlterTableOperations.build_column_operations(a,b)
54
+ ops = @subject.build_column_operations(a,b)
51
55
 
52
- ops.first.up.should == "set_column_default :foo, 2"
56
+ ops.first.should == "set_column_default :foo, 2"
53
57
  end
54
58
 
55
59
  it "should only return 1 operation if the default and other values are different" do
56
60
  a = build_column(:name => :foo, :column_type => :integer, :default => 1)
57
61
  b = build_column(:name => :foo, :column_type => :smallint, :default => 2)
58
- ops = Sequel::Schema::AlterTableOperations.build_column_operations(a,b)
62
+ ops = @subject.build_column_operations(a,b)
59
63
 
60
64
  ops.size.should == 1
61
- ops.first.up.should == "set_column_type :foo, :smallint, :default => 2"
65
+ ops.first.should == "set_column_type :foo, :smallint, :default => 2"
62
66
  end
63
67
 
64
68
  it "should return a ChangeColumn operation if the elements are different" do
65
69
  a = build_column(:name => :foo, :column_type => :enum, :elements => ["A"])
66
70
  b = build_column(:name => :foo, :column_type => :enum, :elements => ["A", "B"])
67
- ops = Sequel::Schema::AlterTableOperations.build_column_operations(a,b)
71
+ ops = @subject.build_column_operations(a,b)
68
72
 
69
- ops.first.up.should == "set_column_type :foo, :enum, :default => nil, :elements => [\"A\", \"B\"]"
73
+ ops.first.should == "set_column_type :foo, :enum, :default => nil, :elements => [\"A\", \"B\"]"
70
74
  end
71
75
  end
72
76
 
@@ -89,7 +93,7 @@ describe "Sequel::Schema::AlterTableOperations.build" do
89
93
  ops = Sequel::Schema::AlterTableOperations.build(table_a,table_b)
90
94
 
91
95
  ops.size.should == 1
92
- ops.first.should be_kind_of(Sequel::Schema::AlterTableOperations::AddColumn)
96
+ ops.first.should =~ /add_column/
93
97
  end
94
98
 
95
99
  it "should return a drop column operation if the column has been removed" do
@@ -100,7 +104,7 @@ describe "Sequel::Schema::AlterTableOperations.build" do
100
104
  ops = Sequel::Schema::AlterTableOperations.build(table_a,table_b)
101
105
 
102
106
  ops.size.should == 1
103
- ops.first.should be_kind_of(Sequel::Schema::AlterTableOperations::DropColumn)
107
+ ops.first.should =~ /drop_column/
104
108
  end
105
109
 
106
110
  it "should return a change column operation if columns are different" do
@@ -111,105 +115,16 @@ describe "Sequel::Schema::AlterTableOperations.build" do
111
115
  ops = Sequel::Schema::AlterTableOperations.build(table_a,table_b)
112
116
 
113
117
  ops.size.should == 1
114
- ops.first.should be_kind_of(Sequel::Schema::AlterTableOperations::ChangeColumn)
118
+ ops.first.should =~ /set_column/
115
119
  end
116
120
 
117
- it "should not output a drop index statement in #up if the index's column is also removed" do
121
+ it "should not output a drop index statement in #change if the index's column is also removed" do
118
122
  table_a = {:name => :example_table,
119
123
  :indexes => {:foo_idx => {:columns => [:foo]}},
120
124
  :columns => [build_column(:name => :foo, :column_type => :integer)]}
121
125
  table_b = {:name => :example_table, :indexes => {}, :columns => []}
122
126
  ops = Sequel::Schema::AlterTableOperations.build(table_a,table_b)
123
127
 
124
- ops.last.should be_kind_of(Sequel::Schema::AlterTableOperations::DropIndex)
125
- ops.last.up.should be_nil
126
- ops.last.down.should == "add_index [:foo], :name => :foo_idx"
127
- end
128
-
129
- it "should not output a drop index statement in #down if the index's column is also added" do
130
- table_a = {:name => :example_table,
131
- :indexes => {},
132
- :columns => [build_column(:name => :foo, :column_type => :integer)]}
133
- table_b = {:name => :example_table, :indexes => {:foo_idx => {:columns => [:foo]}}, :columns => []}
134
- ops = Sequel::Schema::AlterTableOperations.build(table_a,table_b)
135
-
136
- ops.last.should be_kind_of(Sequel::Schema::AlterTableOperations::AddIndex)
137
- ops.last.up.should == "add_index [:foo], :name => :foo_idx"
138
- ops.last.down.should be_nil
139
- end
140
- end
141
-
142
- describe Sequel::Schema::AlterTableOperations::AddColumn do
143
- before(:each) { @mock_column = mock() }
144
-
145
- it "should ask the column for its add column statement on #up" do
146
- @mock_column.should_receive(:add_statement).and_return("add")
147
- @mock_column.should_receive(:drop_statement)
148
- Sequel::Schema::AlterTableOperations::AddColumn.new(@mock_column).up.should == "add"
149
- end
150
-
151
- it "should ask the column for its drop column statement on #down" do
152
- @mock_column.should_receive(:add_statement)
153
- @mock_column.should_receive(:drop_statement).and_return("drop")
154
- Sequel::Schema::AlterTableOperations::AddColumn.new(@mock_column).down.should == "drop"
155
- end
156
- end
157
-
158
- describe Sequel::Schema::AlterTableOperations::DropColumn do
159
- before(:each) { @mock_column = mock() }
160
-
161
- it "should ask the column for its drop column statement on #up" do
162
- @mock_column.should_receive(:add_statement)
163
- @mock_column.should_receive(:drop_statement).and_return("drop")
164
- Sequel::Schema::AlterTableOperations::DropColumn.new(@mock_column).up.should == "drop"
165
- end
166
-
167
- it "should ask the column for its add column statement on #down" do
168
- @mock_column.should_receive(:drop_statement)
169
- @mock_column.should_receive(:add_statement).and_return("add")
170
- Sequel::Schema::AlterTableOperations::DropColumn.new(@mock_column).down.should == "add"
171
- end
172
- end
173
-
174
- describe Sequel::Schema::AlterTableOperations::ChangeColumn do
175
- it "should ask the new column for statement on #up" do
176
- new = mock(:new)
177
- old = mock(:old)
178
- old.should_receive(:change_type_statement)
179
- new.should_receive(:change_type_statement).and_return("new")
180
- Sequel::Schema::AlterTableOperations::ChangeColumn.new(old, new, :change_type_statement).up.should == "new"
181
- end
182
-
183
- it "should ask the old column for statement on #down" do
184
- new = mock(:new)
185
- old = mock(:old)
186
- old.should_receive(:change_type_statement).and_return("old")
187
- new.should_receive(:change_type_statement)
188
- Sequel::Schema::AlterTableOperations::ChangeColumn.new(old, new, :change_type_statement).down
189
- end
190
- end
191
-
192
-
193
- describe Sequel::Schema::AlterTableOperations::AddIndex do
194
- it "should add the index on #up" do
195
- Sequel::Schema::AlterTableOperations::AddIndex.new(:foo_index, :foo, true).up.
196
- should == "add_index :foo, :name => :foo_index, :unique => true"
197
- end
198
-
199
- it "should drop the index on #down" do
200
- Sequel::Schema::AlterTableOperations::AddIndex.new(:foo_index, :foo, true).down.
201
- should == "drop_index :foo, :name => :foo_index"
202
- end
203
- end
204
-
205
- describe Sequel::Schema::AlterTableOperations::DropIndex do
206
- it "should add the index on #down" do
207
- Sequel::Schema::AlterTableOperations::DropIndex.new(:foo_index, :foo, true).down.
208
- should == "add_index :foo, :name => :foo_index, :unique => true"
209
- end
210
-
211
- it "should drop the index on #up" do
212
- Sequel::Schema::AlterTableOperations::DropIndex.new(:foo_index, :foo, true).up.
213
- should == "drop_index :foo, :name => :foo_index"
128
+ ops.last.should be_nil
214
129
  end
215
130
  end
@@ -0,0 +1,76 @@
1
+ require File.dirname(__FILE__) + "/spec_helper"
2
+
3
+ describe Sequel::Schema::DbIndex do
4
+ it "should have a name" do
5
+ Sequel::Schema::DbIndex.new('foo_index', :foo).name.should == :foo_index
6
+ end
7
+
8
+ it "can have columns" do
9
+ Sequel::Schema::DbIndex.new('foo_index', [:foo, :bar]).columns.should == [:foo, :bar]
10
+ end
11
+
12
+ it "converts a single column symbol to a 1 element array of columns" do
13
+ Sequel::Schema::DbIndex.new('foo_index', :foo).columns.should == [:foo]
14
+ end
15
+
16
+ it "is not unique by default" do
17
+ Sequel::Schema::DbIndex.new('foo_index', :foo).should_not be_unique
18
+ end
19
+
20
+ it "can be unique" do
21
+ Sequel::Schema::DbIndex.new('foo_index', :foo, true).should be_unique
22
+ end
23
+
24
+ it "should respond to multi_column?" do
25
+ Sequel::Schema::DbIndex.new('foo_index', :foo, true).should_not be_multi_column
26
+ Sequel::Schema::DbIndex.new('foo_index', [:foo, :bar], true).should be_multi_column
27
+ end
28
+
29
+ it "should be equal when compared with ==" do
30
+ i1 = Sequel::Schema::DbIndex.new('foo_idx', :foo, true)
31
+
32
+ i1.should == Sequel::Schema::DbIndex.new('foo_idx', :foo, true)
33
+ i1.should == Sequel::Schema::DbIndex.new('foo_idx', [:foo], true)
34
+ i1.should_not == Sequel::Schema::DbIndex.new('foo_idx', :foo, false)
35
+ i1.should_not == Sequel::Schema::DbIndex.new('foo', :foo, true)
36
+ i1.should_not == Sequel::Schema::DbIndex.new('foo_idx', :bar, true)
37
+ end
38
+
39
+ it "should be equal when compared with eql?" do
40
+ i1 = Sequel::Schema::DbIndex.new('foo_idx', :foo, true)
41
+
42
+ i1.hash.should == Sequel::Schema::DbIndex.new('foo_idx', :foo, true).hash
43
+ i1.should be_eql(Sequel::Schema::DbIndex.new('foo_idx', :foo, true))
44
+ end
45
+
46
+ it "can be built from a hash returned by Sequel::Database#indexes" do
47
+ hsh = {:foo_idx => {:columns => [:foo], :unique => true}}
48
+ Sequel::Schema::DbIndex.build_from_hash(hsh).should ==
49
+ [Sequel::Schema::DbIndex.new(:foo_idx, :foo, true)]
50
+ end
51
+
52
+ it "should have a define statement" do
53
+ Sequel::Schema::DbIndex.new(:foo_idx, :foo, true).define_statement.should ==
54
+ "index :foo, :name => :foo_idx, :unique => true"
55
+ end
56
+
57
+ it "should have a define statement for multiple columns" do
58
+ Sequel::Schema::DbIndex.new(:foo_idx, [:foo, :bar], true).define_statement.should ==
59
+ "index [:foo, :bar], :name => :foo_idx, :unique => true"
60
+ end
61
+
62
+ it "should not output the unique value if it is false" do
63
+ Sequel::Schema::DbIndex.new(:foo_idx, :foo).define_statement.should ==
64
+ "index :foo, :name => :foo_idx"
65
+ end
66
+
67
+ it "should have an add_index statement" do
68
+ Sequel::Schema::DbIndex.new(:foo_idx, :foo, true).add_statement.should ==
69
+ "add_index :foo, :name => :foo_idx, :unique => true"
70
+ end
71
+
72
+ it "should have an drop_index statement" do
73
+ Sequel::Schema::DbIndex.new(:foo_idx, :foo, true).drop_statement.should ==
74
+ "drop_index :foo, :name => :foo_idx"
75
+ end
76
+ end
@@ -16,15 +16,11 @@ describe Sequel::MigrationBuilder do
16
16
 
17
17
  expected = <<-END
18
18
  Sequel.migration do
19
- up do
19
+ change do
20
20
  create_table :example_table do
21
21
  integer :foo, :null => false
22
22
  end
23
23
  end
24
-
25
- down do
26
- drop_table :example_table
27
- end
28
24
  end
29
25
  END
30
26
 
@@ -45,7 +41,7 @@ END
45
41
 
46
42
  expected = <<-END
47
43
  Sequel.migration do
48
- up do
44
+ change do
49
45
  create_table :example_table do
50
46
  integer :foo, :null => false
51
47
  varchar :bar, :null => false
@@ -55,11 +51,6 @@ Sequel.migration do
55
51
  integer :foo
56
52
  end
57
53
  end
58
-
59
- down do
60
- drop_table :example_table_2
61
- drop_table :example_table
62
- end
63
54
  end
64
55
  END
65
56
 
@@ -140,7 +131,7 @@ END
140
131
 
141
132
  it "should return an alter table statement with column changes for #generate_up" do
142
133
  expected = <<-END
143
- up do
134
+ change do
144
135
  alter_table :example_table do
145
136
  set_column_type :foo, :integer, :default => nil
146
137
  set_column_allow_null :foo, false
@@ -149,21 +140,8 @@ up do
149
140
  end
150
141
  end
151
142
  END
152
- Sequel::MigrationBuilder.new(@mock_db).generate_up(@tables).join("\n").should == expected
153
- end
154
-
155
- it "should return an alter table statement with column changes for #generate_down" do
156
- expected = <<-END
157
- down do
158
- alter_table :example_table do
159
- set_column_type :foo, :smallint, :default => 10, :unsigned => true
160
- set_column_allow_null :foo, true
161
- drop_column :bar
162
- drop_index :foo, :name => :foo_index
163
- end
164
- end
165
- END
166
- Sequel::MigrationBuilder.new(@mock_db).generate_down(@tables).join("\n").should == expected.strip
143
+ Sequel::MigrationBuilder.new(@mock_db).
144
+ generate_migration_body(@tables).join("\n").should == expected.strip
167
145
  end
168
146
  end
169
147
 
@@ -173,7 +151,7 @@ END
173
151
  mock_db.should_receive(:tables).at_least(:once).and_return([:example_table])
174
152
 
175
153
  expected = <<-END
176
- up do
154
+ change do
177
155
  drop_table :example_table
178
156
  end
179
157
  END
metadata CHANGED
@@ -1,12 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sequel_migration_builder
3
3
  version: !ruby/object:Gem::Version
4
+ hash: 23
4
5
  prerelease: false
5
6
  segments:
6
7
  - 0
7
- - 1
8
- - 4
9
- version: 0.1.4
8
+ - 2
9
+ - 0
10
+ version: 0.2.0
10
11
  platform: ruby
11
12
  authors:
12
13
  - Roland Swingler
@@ -14,30 +15,34 @@ autorequire:
14
15
  bindir: bin
15
16
  cert_chain: []
16
17
 
17
- date: 2010-08-13 00:00:00 +01:00
18
+ date: 2011-01-13 00:00:00 +00:00
18
19
  default_executable:
19
20
  dependencies:
20
21
  - !ruby/object:Gem::Dependency
21
22
  name: sequel
22
23
  prerelease: false
23
24
  requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
24
26
  requirements:
25
27
  - - ">="
26
28
  - !ruby/object:Gem::Version
29
+ hash: 79
27
30
  segments:
28
31
  - 3
29
- - 12
32
+ - 18
30
33
  - 0
31
- version: 3.12.0
34
+ version: 3.18.0
32
35
  type: :runtime
33
36
  version_requirements: *id001
34
37
  - !ruby/object:Gem::Dependency
35
38
  name: rspec
36
39
  prerelease: false
37
40
  requirement: &id002 !ruby/object:Gem::Requirement
41
+ none: false
38
42
  requirements:
39
43
  - - ">="
40
44
  - !ruby/object:Gem::Version
45
+ hash: 13
41
46
  segments:
42
47
  - 1
43
48
  - 2
@@ -57,6 +62,7 @@ extra_rdoc_files:
57
62
  files:
58
63
  - .document
59
64
  - .gitignore
65
+ - CHANGELOG
60
66
  - LICENSE
61
67
  - README.rdoc
62
68
  - Rakefile
@@ -64,10 +70,12 @@ files:
64
70
  - lib/sequel/migration_builder.rb
65
71
  - lib/sequel/schema/alter_table_operations.rb
66
72
  - lib/sequel/schema/db_column.rb
73
+ - lib/sequel/schema/db_index.rb
67
74
  - lib/sequel/schema/db_schema_parser.rb
68
75
  - sequel_migration_builder.gemspec
69
76
  - spec/alter_table_operations_spec.rb
70
77
  - spec/db_column_spec.rb
78
+ - spec/db_index_spec.rb
71
79
  - spec/db_schema_parser_spec.rb
72
80
  - spec/migration_builder_spec.rb
73
81
  - spec/spec.opts
@@ -82,29 +90,34 @@ rdoc_options:
82
90
  require_paths:
83
91
  - lib
84
92
  required_ruby_version: !ruby/object:Gem::Requirement
93
+ none: false
85
94
  requirements:
86
95
  - - ">="
87
96
  - !ruby/object:Gem::Version
97
+ hash: 3
88
98
  segments:
89
99
  - 0
90
100
  version: "0"
91
101
  required_rubygems_version: !ruby/object:Gem::Requirement
102
+ none: false
92
103
  requirements:
93
104
  - - ">="
94
105
  - !ruby/object:Gem::Version
106
+ hash: 3
95
107
  segments:
96
108
  - 0
97
109
  version: "0"
98
110
  requirements: []
99
111
 
100
112
  rubyforge_project:
101
- rubygems_version: 1.3.6
113
+ rubygems_version: 1.3.7
102
114
  signing_key:
103
115
  specification_version: 3
104
116
  summary: Build Sequel Migrations based on the differences between two schemas
105
117
  test_files:
106
118
  - spec/alter_table_operations_spec.rb
107
119
  - spec/db_column_spec.rb
120
+ - spec/db_index_spec.rb
108
121
  - spec/db_schema_parser_spec.rb
109
122
  - spec/migration_builder_spec.rb
110
123
  - spec/spec_helper.rb