sequel_migration_builder 0.0.5 → 0.1.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/README.rdoc CHANGED
@@ -21,6 +21,10 @@ as a hash. A sample YAML version might look like:
21
21
  primary_key: id
22
22
  table_options:
23
23
  engine: myisam
24
+ indexes:
25
+ foo_index_name:
26
+ columns: foo
27
+ unique: true
24
28
  columns:
25
29
  - name: id
26
30
  column_type: integer
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.5
1
+ 0.1.0
@@ -114,6 +114,14 @@ module Sequel
114
114
  table[:columns].each do |c|
115
115
  add_line Schema::DbColumn.build_from_hash(c).define_statement
116
116
  end
117
+ if table[:indexes]
118
+ add_blank_line
119
+ table[:indexes].each do |name, options|
120
+ opts = options.clone
121
+ columns = opts.delete(:columns)
122
+ add_line "index #{columns.inspect}, :name => #{name.to_sym.inspect}#{pretty_hash(opts)}"
123
+ end
124
+ end
117
125
  if table[:primary_key]
118
126
  add_blank_line
119
127
  add_line "primary_key #{table[:primary_key].inspect}"
@@ -139,7 +147,7 @@ module Sequel
139
147
  # Returns a string representing a hash as ':foo => :bar'
140
148
  # rather than '{:foo=.:bar}'
141
149
  def pretty_hash(hash)
142
- ", " + hash.inspect.gsub(/^\{|\}$/,'').gsub("=>", " => ") if hash
150
+ ", " + hash.inspect.gsub(/^\{|\}$/,'').gsub("=>", " => ") if hash && ! hash.empty?
143
151
  end
144
152
 
145
153
  def table_names(tables)
@@ -17,7 +17,24 @@ module Sequel
17
17
  end.flatten
18
18
 
19
19
  new_column_names = new_table[:columns].map {|c| c.name }
20
- operations + (db_columns.keys - new_column_names).map {|column| DropColumn.new(column) }
20
+ operations += (db_columns.keys - new_column_names).map {|name| DropColumn.new(db_columns[name]) }
21
+
22
+ db_indexes = db_table[:indexes] || {}
23
+ new_indexes = new_table[:indexes] || {}
24
+
25
+ operations += (db_indexes.keys - new_indexes.keys).map do |index_name|
26
+ DropIndex.new(index_name,
27
+ db_indexes[index_name][:columns],
28
+ db_indexes[index_name][:unique])
29
+ end
30
+
31
+ operations += (new_indexes.keys - db_indexes.keys).map do |index_name|
32
+ AddIndex.new(index_name,
33
+ new_indexes[index_name][:columns],
34
+ new_indexes[index_name][:unique])
35
+ end
36
+
37
+ operations
21
38
  end
22
39
 
23
40
  # Returns an array of operations to change the current database
@@ -35,49 +52,55 @@ module Sequel
35
52
  result.map {|k| ChangeColumn.new(db_column, new_column, k) }
36
53
  end
37
54
 
55
+ # Base alter table operation class. Each operation will return
56
+ # Sequel::Migration statement(s) to alter the table.
57
+ class Operation
58
+ # Returns the statement for the up part of the migration
59
+ attr_reader :up
60
+
61
+ # Returns the statement for the down part of the operation
62
+ attr_reader :down
63
+ end
64
+
38
65
  # Changes a column.
39
- class ChangeColumn
66
+ class ChangeColumn < Operation
40
67
  def initialize(old_column, new_column, statement)
41
- @old_column, @new_column = old_column, new_column
42
- @statement_method = statement
43
- end
44
-
45
- def up
46
- @new_column.__send__(@statement_method)
47
- end
48
-
49
- def down
50
- @old_column.__send__(@statement_method)
68
+ @up = new_column.__send__(statement)
69
+ @down = old_column.__send__(statement)
51
70
  end
52
71
  end
53
72
 
54
73
  # Adds a column.
55
- class AddColumn
74
+ class AddColumn < Operation
56
75
  def initialize(column)
57
- @column = column
58
- end
59
-
60
- def up
61
- @column.add_statement
62
- end
63
-
64
- def down
65
- @column.drop_statement
76
+ @up = column.add_statement
77
+ @down = column.drop_statement
66
78
  end
67
79
  end
68
80
 
69
81
  # Drops a column.
70
- class DropColumn
82
+ class DropColumn < Operation
71
83
  def initialize(column)
72
- @column = column
84
+ @up = column.drop_statement
85
+ @down = column.add_statement
73
86
  end
87
+ end
74
88
 
75
- def up
76
- @column.drop_statement
89
+ # Adds an index.
90
+ class AddIndex < Operation
91
+ def initialize(name, columns, unique)
92
+ @up = "add_index #{columns.inspect}, :name => #{name.inspect}"
93
+ @up << ", :unique => true" if unique
94
+ @down = "drop_index #{columns.inspect}, :name => #{name.inspect}"
77
95
  end
96
+ end
78
97
 
79
- def down
80
- @column.add_statement
98
+ # Drops an index.
99
+ class DropIndex < Operation
100
+ def initialize(name, columns, unique)
101
+ @up = "drop_index #{columns.inspect}, :name => #{name.inspect}"
102
+ @down = "add_index #{columns.inspect}, :name => #{name.inspect}"
103
+ @down << ", :unique => true" if unique
81
104
  end
82
105
  end
83
106
  end
@@ -14,7 +14,7 @@ module Sequel
14
14
  INTEGER_TYPES = [:tinyint, :integer, :smallint, :mediumint, :bigint]
15
15
 
16
16
  # Database column types that hold fractional values.
17
- DECIMAL_TYPES = [:decimal, :float, :bigdecimal]
17
+ DECIMAL_TYPES = [:decimal, :float, :double, :real]
18
18
 
19
19
  # All numeric database column types.
20
20
  NUMERIC_TYPES = INTEGER_TYPES + DECIMAL_TYPES
@@ -81,7 +81,7 @@ module Sequel
81
81
  }.select {|attribute, method| __send__(method, attribute, other) }.map {|a| a.first }.to_set
82
82
  end
83
83
 
84
- # Returns true if this column is numeric
84
+ # Returns true if this column is numeric.
85
85
  #
86
86
  def numeric?
87
87
  NUMERIC_TYPES.include?(column_type)
@@ -28,7 +28,10 @@ module Sequel
28
28
  #
29
29
  def parse_db_schema
30
30
  @db.tables.inject({}) do |result, table_name|
31
- result[table_name] = {:columns => parse_table_schema(@db.schema(table_name))}
31
+ result[table_name] = {
32
+ :indexes => @db.indexes(table_name),
33
+ :columns => parse_table_schema(@db.schema(table_name))
34
+ }
32
35
  result
33
36
  end
34
37
  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.0.5"
8
+ s.version = "0.1.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-06-23}
12
+ s.date = %q{2010-07-02}
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 = [
@@ -111,13 +111,15 @@ describe Sequel::Schema::AlterTableOperations::AddColumn do
111
111
  before(:each) { @mock_column = mock() }
112
112
 
113
113
  it "should ask the column for its add column statement on #up" do
114
- @mock_column.should_receive(:add_statement)
115
- Sequel::Schema::AlterTableOperations::AddColumn.new(@mock_column).up
114
+ @mock_column.should_receive(:add_statement).and_return("add")
115
+ @mock_column.should_receive(:drop_statement)
116
+ Sequel::Schema::AlterTableOperations::AddColumn.new(@mock_column).up.should == "add"
116
117
  end
117
118
 
118
119
  it "should ask the column for its drop column statement on #down" do
119
- @mock_column.should_receive(:drop_statement)
120
- Sequel::Schema::AlterTableOperations::AddColumn.new(@mock_column).down
120
+ @mock_column.should_receive(:add_statement)
121
+ @mock_column.should_receive(:drop_statement).and_return("drop")
122
+ Sequel::Schema::AlterTableOperations::AddColumn.new(@mock_column).down.should == "drop"
121
123
  end
122
124
  end
123
125
 
@@ -125,13 +127,15 @@ describe Sequel::Schema::AlterTableOperations::DropColumn do
125
127
  before(:each) { @mock_column = mock() }
126
128
 
127
129
  it "should ask the column for its drop column statement on #up" do
128
- @mock_column.should_receive(:drop_statement)
129
- Sequel::Schema::AlterTableOperations::DropColumn.new(@mock_column).up
130
+ @mock_column.should_receive(:add_statement)
131
+ @mock_column.should_receive(:drop_statement).and_return("drop")
132
+ Sequel::Schema::AlterTableOperations::DropColumn.new(@mock_column).up.should == "drop"
130
133
  end
131
134
 
132
135
  it "should ask the column for its add column statement on #down" do
133
- @mock_column.should_receive(:add_statement)
134
- Sequel::Schema::AlterTableOperations::DropColumn.new(@mock_column).down
136
+ @mock_column.should_receive(:drop_statement)
137
+ @mock_column.should_receive(:add_statement).and_return("add")
138
+ Sequel::Schema::AlterTableOperations::DropColumn.new(@mock_column).down.should == "add"
135
139
  end
136
140
  end
137
141
 
@@ -139,14 +143,41 @@ describe Sequel::Schema::AlterTableOperations::ChangeColumn do
139
143
  it "should ask the new column for statement on #up" do
140
144
  new = mock(:new)
141
145
  old = mock(:old)
142
- new.should_receive(:change_type_statement)
143
- Sequel::Schema::AlterTableOperations::ChangeColumn.new(old, new, :change_type_statement).up
146
+ old.should_receive(:change_type_statement)
147
+ new.should_receive(:change_type_statement).and_return("new")
148
+ Sequel::Schema::AlterTableOperations::ChangeColumn.new(old, new, :change_type_statement).up.should == "new"
144
149
  end
145
150
 
146
- it "should ask the new column for statement on #down" do
151
+ it "should ask the old column for statement on #down" do
147
152
  new = mock(:new)
148
153
  old = mock(:old)
149
- old.should_receive(:change_type_statement)
154
+ old.should_receive(:change_type_statement).and_return("old")
155
+ new.should_receive(:change_type_statement)
150
156
  Sequel::Schema::AlterTableOperations::ChangeColumn.new(old, new, :change_type_statement).down
151
157
  end
152
158
  end
159
+
160
+
161
+ describe Sequel::Schema::AlterTableOperations::AddIndex do
162
+ it "should add the index on #up" do
163
+ Sequel::Schema::AlterTableOperations::AddIndex.new(:foo_index, :foo, true).up.
164
+ should == "add_index :foo, :name => :foo_index, :unique => true"
165
+ end
166
+
167
+ it "should drop the index on #down" do
168
+ Sequel::Schema::AlterTableOperations::AddIndex.new(:foo_index, :foo, true).down.
169
+ should == "drop_index :foo, :name => :foo_index"
170
+ end
171
+ end
172
+
173
+ describe Sequel::Schema::AlterTableOperations::DropIndex do
174
+ it "should add the index on #down" do
175
+ Sequel::Schema::AlterTableOperations::DropIndex.new(:foo_index, :foo, true).down.
176
+ should == "add_index :foo, :name => :foo_index, :unique => true"
177
+ end
178
+
179
+ it "should drop the index on #up" do
180
+ Sequel::Schema::AlterTableOperations::DropIndex.new(:foo_index, :foo, true).up.
181
+ should == "drop_index :foo, :name => :foo_index"
182
+ end
183
+ end
@@ -114,6 +114,7 @@ describe "Sequel::Schema::DbSchemaParser#parse_db_schema" do
114
114
  mock_db = mock(:db)
115
115
  mock_db.should_receive(:tables).at_least(:once).and_return([:table1])
116
116
  mock_db.should_receive(:schema).with(:table1).and_return([])
117
+ mock_db.should_receive(:indexes).with(:table1)
117
118
 
118
119
  @parser = Sequel::Schema::DbSchemaParser.for_db(mock_db)
119
120
  @parser.parse_db_schema.keys.should == [:table1]
@@ -107,13 +107,35 @@ END
107
107
  should == expected.strip
108
108
  end
109
109
 
110
+ it "should add indexes to the create_table statement" do
111
+ mock_db = mock(:database)
112
+ mock_db.should_receive(:tables).at_least(:once).and_return([])
113
+ table = {
114
+ :indexes => {:foo_index => {:columns => :foo, :unique => true}},
115
+ :columns => [{:name => :foo, :column_type => :integer}]
116
+ }
117
+
118
+ expected = <<-END
119
+ create_table :example_table do
120
+ integer :foo, :null => false
121
+
122
+ index :foo, :name => :foo_index, :unique => true
123
+ end
124
+ END
125
+
126
+ Sequel::MigrationBuilder.new(mock_db).create_table_statement(:example_table, table).join("\n").
127
+ should == expected.strip
128
+ end
129
+
110
130
  context "when a table needs to be altered" do
111
131
  before :each do
112
132
  @tables = { :example_table =>
113
- {:columns => [{:name => :foo, :column_type => :integer}, {:name => :bar, :column_type => :varchar}]}
133
+ { :indexes => {:foo_index => {:columns => :foo, :unique => true}},
134
+ :columns => [{:name => :foo, :column_type => :integer}, {:name => :bar, :column_type => :varchar}]}
114
135
  }
115
136
  @mock_db = mock(:database)
116
137
  @mock_db.should_receive(:tables).at_least(:once).and_return([:example_table])
138
+ @mock_db.should_receive(:indexes).with(:example_table).and_return({})
117
139
  @mock_db.should_receive(:schema).with(:example_table).and_return([[:foo, {:type => :integer, :db_type => "smallint(5) unsigned", :allow_null => true, :ruby_default => 10}]])
118
140
 
119
141
  end
@@ -125,6 +147,7 @@ up do
125
147
  set_column_type :foo, :integer, :default => nil
126
148
  set_column_allow_null :foo, false
127
149
  add_column :bar, :varchar, :null => false
150
+ add_index :foo, :name => :foo_index, :unique => true
128
151
  end
129
152
  end
130
153
  END
@@ -138,6 +161,7 @@ down do
138
161
  set_column_type :foo, :smallint, :default => 10, :unsigned => true
139
162
  set_column_allow_null :foo, true
140
163
  drop_column :bar
164
+ drop_index :foo, :name => :foo_index
141
165
  end
142
166
  end
143
167
  END
metadata CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
4
4
  prerelease: false
5
5
  segments:
6
6
  - 0
7
+ - 1
7
8
  - 0
8
- - 5
9
- version: 0.0.5
9
+ version: 0.1.0
10
10
  platform: ruby
11
11
  authors:
12
12
  - Roland Swingler
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-06-23 00:00:00 +01:00
17
+ date: 2010-07-02 00:00:00 +01:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency