sequel_migration_builder 0.1.4 → 0.2.0

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