dm-hibernate-migrations 1.0.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/lib/dm-migrations.rb +3 -0
- data/lib/dm-migrations/adapters/dm-do-adapter.rb +284 -0
- data/lib/dm-migrations/adapters/dm-mysql-adapter.rb +283 -0
- data/lib/dm-migrations/adapters/dm-oracle-adapter.rb +321 -0
- data/lib/dm-migrations/adapters/dm-postgres-adapter.rb +159 -0
- data/lib/dm-migrations/adapters/dm-sqlite-adapter.rb +96 -0
- data/lib/dm-migrations/adapters/dm-sqlserver-adapter.rb +177 -0
- data/lib/dm-migrations/adapters/dm-yaml-adapter.rb +23 -0
- data/lib/dm-migrations/auto_migration.rb +237 -0
- data/lib/dm-migrations/migration.rb +217 -0
- data/lib/dm-migrations/migration_runner.rb +85 -0
- data/lib/dm-migrations/sql.rb +5 -0
- data/lib/dm-migrations/sql/column.rb +5 -0
- data/lib/dm-migrations/sql/mysql.rb +53 -0
- data/lib/dm-migrations/sql/postgres.rb +78 -0
- data/lib/dm-migrations/sql/sqlite.rb +45 -0
- data/lib/dm-migrations/sql/table.rb +15 -0
- data/lib/dm-migrations/sql/table_creator.rb +102 -0
- data/lib/dm-migrations/sql/table_modifier.rb +51 -0
- data/lib/spec/example/migration_example_group.rb +73 -0
- data/lib/spec/matchers/migration_matchers.rb +106 -0
- data/spec/integration/auto_migration_spec.rb +506 -0
- data/spec/integration/migration_runner_spec.rb +89 -0
- data/spec/integration/migration_spec.rb +138 -0
- data/spec/integration/sql_spec.rb +190 -0
- data/spec/isolated/require_after_setup_spec.rb +30 -0
- data/spec/isolated/require_before_setup_spec.rb +30 -0
- data/spec/isolated/require_spec.rb +25 -0
- data/spec/rcov.opts +6 -0
- data/spec/spec.opts +4 -0
- data/spec/spec_helper.rb +16 -0
- data/spec/unit/migration_spec.rb +453 -0
- data/spec/unit/sql/column_spec.rb +14 -0
- data/spec/unit/sql/postgres_spec.rb +97 -0
- data/spec/unit/sql/sqlite_extensions_spec.rb +108 -0
- data/spec/unit/sql/table_creator_spec.rb +94 -0
- data/spec/unit/sql/table_modifier_spec.rb +49 -0
- data/spec/unit/sql/table_spec.rb +28 -0
- data/spec/unit/sql_spec.rb +7 -0
- metadata +157 -0
@@ -0,0 +1,96 @@
|
|
1
|
+
require 'dm-migrations/auto_migration'
|
2
|
+
require 'dm-migrations/adapters/dm-do-adapter'
|
3
|
+
|
4
|
+
module DataMapper
|
5
|
+
module Migrations
|
6
|
+
module SqliteAdapter
|
7
|
+
|
8
|
+
include DataObjectsAdapter
|
9
|
+
|
10
|
+
# @api private
|
11
|
+
def self.included(base)
|
12
|
+
base.extend DataObjectsAdapter::ClassMethods
|
13
|
+
base.extend ClassMethods
|
14
|
+
end
|
15
|
+
|
16
|
+
# @api semipublic
|
17
|
+
def storage_exists?(storage_name)
|
18
|
+
table_info(storage_name).any?
|
19
|
+
end
|
20
|
+
|
21
|
+
# @api semipublic
|
22
|
+
def field_exists?(storage_name, column_name)
|
23
|
+
table_info(storage_name).any? do |row|
|
24
|
+
row.name == column_name
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
module SQL #:nodoc:
|
29
|
+
# private ## This cannot be private for current migrations
|
30
|
+
|
31
|
+
# @api private
|
32
|
+
def supports_serial?
|
33
|
+
@supports_serial ||= sqlite_version >= '3.1.0'
|
34
|
+
end
|
35
|
+
|
36
|
+
# @api private
|
37
|
+
def supports_drop_table_if_exists?
|
38
|
+
@supports_drop_table_if_exists ||= sqlite_version >= '3.3.0'
|
39
|
+
end
|
40
|
+
|
41
|
+
# @api private
|
42
|
+
def table_info(table_name)
|
43
|
+
select("PRAGMA table_info(#{quote_name(table_name)})")
|
44
|
+
end
|
45
|
+
|
46
|
+
# @api private
|
47
|
+
def create_table_statement(connection, model, properties)
|
48
|
+
statement = <<-SQL.compress_lines
|
49
|
+
CREATE TABLE #{quote_name(model.storage_name(name))}
|
50
|
+
(#{properties.map { |property| property_schema_statement(connection, property_schema_hash(property)) }.join(', ')}
|
51
|
+
SQL
|
52
|
+
|
53
|
+
# skip adding the primary key if one of the columns is serial. In
|
54
|
+
# SQLite the serial column must be the primary key, so it has already
|
55
|
+
# been defined
|
56
|
+
unless properties.any? { |property| property.serial? }
|
57
|
+
statement << ", PRIMARY KEY(#{properties.key.map { |property| quote_name(property.field) }.join(', ')})"
|
58
|
+
end
|
59
|
+
|
60
|
+
statement << ')'
|
61
|
+
statement
|
62
|
+
end
|
63
|
+
|
64
|
+
# @api private
|
65
|
+
def property_schema_statement(connection, schema)
|
66
|
+
statement = super
|
67
|
+
|
68
|
+
if supports_serial? && schema[:serial]
|
69
|
+
statement << ' PRIMARY KEY AUTOINCREMENT'
|
70
|
+
end
|
71
|
+
|
72
|
+
statement
|
73
|
+
end
|
74
|
+
|
75
|
+
# @api private
|
76
|
+
def sqlite_version
|
77
|
+
@sqlite_version ||= select('SELECT sqlite_version(*)').first.freeze
|
78
|
+
end
|
79
|
+
end # module SQL
|
80
|
+
|
81
|
+
include SQL
|
82
|
+
|
83
|
+
module ClassMethods
|
84
|
+
# Types for SQLite 3 databases.
|
85
|
+
#
|
86
|
+
# @return [Hash] types for SQLite 3 databases.
|
87
|
+
#
|
88
|
+
# @api private
|
89
|
+
def type_map
|
90
|
+
@type_map ||= super.merge(Class => { :primitive => 'VARCHAR' }).freeze
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
@@ -0,0 +1,177 @@
|
|
1
|
+
require 'dm-migrations/auto_migration'
|
2
|
+
require 'dm-migrations/adapters/dm-do-adapter'
|
3
|
+
|
4
|
+
module DataMapper
|
5
|
+
module Migrations
|
6
|
+
module SqlserverAdapter
|
7
|
+
|
8
|
+
DEFAULT_CHARACTER_SET = 'utf8'.freeze
|
9
|
+
|
10
|
+
include DataObjectsAdapter
|
11
|
+
|
12
|
+
# @api private
|
13
|
+
def self.included(base)
|
14
|
+
base.extend DataObjectsAdapter::ClassMethods
|
15
|
+
base.extend ClassMethods
|
16
|
+
end
|
17
|
+
|
18
|
+
# @api semipublic
|
19
|
+
def storage_exists?(storage_name)
|
20
|
+
select("SELECT name FROM sysobjects WHERE name LIKE ?", storage_name).first == storage_name
|
21
|
+
end
|
22
|
+
|
23
|
+
# @api semipublic
|
24
|
+
def field_exists?(storage_name, field_name)
|
25
|
+
result = select("SELECT c.name FROM sysobjects as o JOIN syscolumns AS c ON o.id = c.id WHERE o.name = #{quote_name(storage_name)} AND c.name LIKE ?", field_name).first
|
26
|
+
result ? result.field == field_name : false
|
27
|
+
end
|
28
|
+
|
29
|
+
module SQL #:nodoc:
|
30
|
+
# private ## This cannot be private for current migrations
|
31
|
+
|
32
|
+
# @api private
|
33
|
+
def supports_serial?
|
34
|
+
true
|
35
|
+
end
|
36
|
+
|
37
|
+
# @api private
|
38
|
+
def supports_drop_table_if_exists?
|
39
|
+
false
|
40
|
+
end
|
41
|
+
|
42
|
+
# @api private
|
43
|
+
def schema_name
|
44
|
+
# TODO: is there a cleaner way to find out the current DB we are connected to?
|
45
|
+
@options[:path].split('/').last
|
46
|
+
end
|
47
|
+
|
48
|
+
# TODO: update dkubb/dm-more/dm-migrations to use schema_name and remove this
|
49
|
+
|
50
|
+
alias db_name schema_name
|
51
|
+
|
52
|
+
# @api private
|
53
|
+
def create_table_statement(connection, model, properties)
|
54
|
+
statement = <<-SQL.compress_lines
|
55
|
+
CREATE TABLE #{quote_name(model.storage_name(name))}
|
56
|
+
(#{properties.map { |property| property_schema_statement(connection, property_schema_hash(property)) }.join(', ')}
|
57
|
+
SQL
|
58
|
+
|
59
|
+
unless properties.any? { |property| property.serial? }
|
60
|
+
statement << ", PRIMARY KEY(#{properties.key.map { |property| quote_name(property.field) }.join(', ')})"
|
61
|
+
end
|
62
|
+
|
63
|
+
statement << ')'
|
64
|
+
statement
|
65
|
+
end
|
66
|
+
|
67
|
+
# @api private
|
68
|
+
def property_schema_hash(property)
|
69
|
+
schema = super
|
70
|
+
|
71
|
+
if property.kind_of?(Property::Integer)
|
72
|
+
min = property.min
|
73
|
+
max = property.max
|
74
|
+
|
75
|
+
schema[:primitive] = integer_column_statement(min..max) if min && max
|
76
|
+
end
|
77
|
+
|
78
|
+
if schema[:primitive] == 'TEXT'
|
79
|
+
schema.delete(:default)
|
80
|
+
end
|
81
|
+
|
82
|
+
schema
|
83
|
+
end
|
84
|
+
|
85
|
+
# @api private
|
86
|
+
def property_schema_statement(connection, schema)
|
87
|
+
if supports_serial? && schema[:serial]
|
88
|
+
statement = quote_name(schema[:name])
|
89
|
+
statement << " #{schema[:primitive]}"
|
90
|
+
|
91
|
+
length = schema[:length]
|
92
|
+
|
93
|
+
if schema[:precision] && schema[:scale]
|
94
|
+
statement << "(#{[ :precision, :scale ].map { |key| connection.quote_value(schema[key]) }.join(', ')})"
|
95
|
+
elsif length
|
96
|
+
statement << "(#{connection.quote_value(length)})"
|
97
|
+
end
|
98
|
+
|
99
|
+
statement << ' IDENTITY'
|
100
|
+
else
|
101
|
+
statement = super
|
102
|
+
end
|
103
|
+
|
104
|
+
statement
|
105
|
+
end
|
106
|
+
|
107
|
+
# @api private
|
108
|
+
def character_set
|
109
|
+
@character_set ||= show_variable('character_set_connection') || DEFAULT_CHARACTER_SET
|
110
|
+
end
|
111
|
+
|
112
|
+
# @api private
|
113
|
+
def collation
|
114
|
+
@collation ||= show_variable('collation_connection') || DEFAULT_COLLATION
|
115
|
+
end
|
116
|
+
|
117
|
+
# @api private
|
118
|
+
def show_variable(name)
|
119
|
+
raise "SqlserverAdapter#show_variable: Not implemented"
|
120
|
+
end
|
121
|
+
|
122
|
+
private
|
123
|
+
|
124
|
+
# Return SQL statement for the integer column
|
125
|
+
#
|
126
|
+
# @param [Range] range
|
127
|
+
# the min/max allowed integers
|
128
|
+
#
|
129
|
+
# @return [String]
|
130
|
+
# the statement to create the integer column
|
131
|
+
#
|
132
|
+
# @api private
|
133
|
+
def integer_column_statement(range)
|
134
|
+
min = range.first
|
135
|
+
max = range.last
|
136
|
+
|
137
|
+
smallint = 2**15
|
138
|
+
integer = 2**31
|
139
|
+
bigint = 2**63
|
140
|
+
|
141
|
+
if min >= 0 && max < 2**8 then 'TINYINT'
|
142
|
+
elsif min >= -smallint && max < smallint then 'SMALLINT'
|
143
|
+
elsif min >= -integer && max < integer then 'INT'
|
144
|
+
elsif min >= -bigint && max < bigint then 'BIGINT'
|
145
|
+
else
|
146
|
+
raise ArgumentError, "min #{min} and max #{max} exceeds supported range"
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
end # module SQL
|
151
|
+
|
152
|
+
include SQL
|
153
|
+
|
154
|
+
module ClassMethods
|
155
|
+
# Types for Sqlserver databases.
|
156
|
+
#
|
157
|
+
# @return [Hash] types for Sqlserver databases.
|
158
|
+
#
|
159
|
+
# @api private
|
160
|
+
def type_map
|
161
|
+
length = Property::String::DEFAULT_LENGTH
|
162
|
+
precision = Property::Numeric::DEFAULT_PRECISION
|
163
|
+
scale = Property::Decimal::DEFAULT_SCALE
|
164
|
+
|
165
|
+
@type_map ||= super.merge(
|
166
|
+
DateTime => { :primitive => 'DATETIME' },
|
167
|
+
Date => { :primitive => 'SMALLDATETIME' },
|
168
|
+
Time => { :primitive => 'SMALLDATETIME' },
|
169
|
+
TrueClass => { :primitive => 'BIT', },
|
170
|
+
Property::Text => { :primitive => 'NVARCHAR', :length => 'max' }
|
171
|
+
).freeze
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'dm-migrations/auto_migration'
|
2
|
+
require 'dm-migrations/adapters/dm-do-adapter'
|
3
|
+
|
4
|
+
module DataMapper
|
5
|
+
module Migrations
|
6
|
+
module YamlAdapter
|
7
|
+
|
8
|
+
def self.included(base)
|
9
|
+
DataMapper.extend(Migrations::SingletonMethods)
|
10
|
+
[ :Repository, :Model ].each do |name|
|
11
|
+
DataMapper.const_get(name).send(:include, Migrations.const_get(name))
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
# @api semipublic
|
16
|
+
def destroy_model_storage(model)
|
17
|
+
yaml_file(model).unlink if yaml_file(model).file?
|
18
|
+
true
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,237 @@
|
|
1
|
+
require 'dm-core'
|
2
|
+
|
3
|
+
module DataMapper
|
4
|
+
module Migrations
|
5
|
+
module SingletonMethods
|
6
|
+
|
7
|
+
# destructively migrates the repository upwards to match model definitions
|
8
|
+
#
|
9
|
+
# @param [Symbol] name repository to act on, :default is the default
|
10
|
+
#
|
11
|
+
# @api public
|
12
|
+
def migrate!(repository_name = nil)
|
13
|
+
repository(repository_name).migrate!
|
14
|
+
end
|
15
|
+
|
16
|
+
# drops and recreates the repository upwards to match model definitions
|
17
|
+
#
|
18
|
+
# @param [Symbol] name repository to act on, :default is the default
|
19
|
+
#
|
20
|
+
# @api public
|
21
|
+
def auto_migrate!(repository_name = nil)
|
22
|
+
repository_execute(:auto_migrate!, repository_name)
|
23
|
+
end
|
24
|
+
|
25
|
+
# @api public
|
26
|
+
def auto_upgrade!(repository_name = nil)
|
27
|
+
repository_execute(:auto_upgrade!, repository_name)
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
# @api semipublic
|
33
|
+
def auto_migrate_down!(repository_name)
|
34
|
+
repository_execute(:auto_migrate_down!, repository_name)
|
35
|
+
end
|
36
|
+
|
37
|
+
# @api semipublic
|
38
|
+
def auto_migrate_up!(repository_name)
|
39
|
+
repository_execute(:auto_migrate_up!, repository_name)
|
40
|
+
end
|
41
|
+
|
42
|
+
# @api private
|
43
|
+
def repository_execute(method, repository_name)
|
44
|
+
DataMapper::Model.descendants.each do |model|
|
45
|
+
model.send(method, repository_name || model.default_repository_name)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
module Repository
|
51
|
+
# Determine whether a particular named storage exists in this repository
|
52
|
+
#
|
53
|
+
# @param [String]
|
54
|
+
# storage_name name of the storage to test for
|
55
|
+
#
|
56
|
+
# @return [Boolean]
|
57
|
+
# true if the data-store +storage_name+ exists
|
58
|
+
#
|
59
|
+
# @api semipublic
|
60
|
+
def storage_exists?(storage_name)
|
61
|
+
adapter = self.adapter
|
62
|
+
if adapter.respond_to?(:storage_exists?)
|
63
|
+
adapter.storage_exists?(storage_name)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
# @api semipublic
|
68
|
+
def upgrade_model_storage(model)
|
69
|
+
adapter = self.adapter
|
70
|
+
if adapter.respond_to?(:upgrade_model_storage)
|
71
|
+
adapter.upgrade_model_storage(model)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
# @api semipublic
|
76
|
+
def create_model_storage(model)
|
77
|
+
adapter = self.adapter
|
78
|
+
if adapter.respond_to?(:create_model_storage)
|
79
|
+
adapter.create_model_storage(model)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
# @api semipublic
|
84
|
+
def destroy_model_storage(model)
|
85
|
+
adapter = self.adapter
|
86
|
+
if adapter.respond_to?(:destroy_model_storage)
|
87
|
+
adapter.destroy_model_storage(model)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
# Destructively automigrates the data-store to match the model.
|
92
|
+
# First migrates all models down and then up.
|
93
|
+
# REPEAT: THIS IS DESTRUCTIVE
|
94
|
+
#
|
95
|
+
# @api public
|
96
|
+
def auto_migrate!
|
97
|
+
DataMapper.auto_migrate!(name)
|
98
|
+
end
|
99
|
+
|
100
|
+
# Safely migrates the data-store to match the model
|
101
|
+
# preserving data already in the data-store
|
102
|
+
#
|
103
|
+
# @api public
|
104
|
+
def auto_upgrade!
|
105
|
+
DataMapper.auto_upgrade!(name)
|
106
|
+
end
|
107
|
+
end # module Repository
|
108
|
+
|
109
|
+
module Model
|
110
|
+
|
111
|
+
# @api private
|
112
|
+
def self.included(mod)
|
113
|
+
mod.descendants.each { |model| model.extend self }
|
114
|
+
end
|
115
|
+
|
116
|
+
# @api semipublic
|
117
|
+
def storage_exists?(repository_name = default_repository_name)
|
118
|
+
repository(repository_name).storage_exists?(storage_name(repository_name))
|
119
|
+
end
|
120
|
+
|
121
|
+
# Destructively automigrates the data-store to match the model
|
122
|
+
# REPEAT: THIS IS DESTRUCTIVE
|
123
|
+
#
|
124
|
+
# @param Symbol repository_name the repository to be migrated
|
125
|
+
#
|
126
|
+
# @api public
|
127
|
+
def auto_migrate!(repository_name = self.repository_name)
|
128
|
+
assert_valid(true)
|
129
|
+
auto_migrate_down!(repository_name)
|
130
|
+
auto_migrate_up!(repository_name)
|
131
|
+
end
|
132
|
+
|
133
|
+
# Safely migrates the data-store to match the model
|
134
|
+
# preserving data already in the data-store
|
135
|
+
#
|
136
|
+
# @param Symbol repository_name the repository to be migrated
|
137
|
+
#
|
138
|
+
# @api public
|
139
|
+
def auto_upgrade!(repository_name = self.repository_name)
|
140
|
+
assert_valid(true)
|
141
|
+
base_model = self.base_model
|
142
|
+
if base_model == self
|
143
|
+
repository(repository_name).upgrade_model_storage(self)
|
144
|
+
else
|
145
|
+
base_model.auto_upgrade!(repository_name)
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
# Destructively migrates the data-store down, which basically
|
150
|
+
# deletes all the models.
|
151
|
+
# REPEAT: THIS IS DESTRUCTIVE
|
152
|
+
#
|
153
|
+
# @param Symbol repository_name the repository to be migrated
|
154
|
+
#
|
155
|
+
# @api private
|
156
|
+
def auto_migrate_down!(repository_name = self.repository_name)
|
157
|
+
assert_valid(true)
|
158
|
+
base_model = self.base_model
|
159
|
+
if base_model == self
|
160
|
+
repository(repository_name).destroy_model_storage(self)
|
161
|
+
else
|
162
|
+
base_model.auto_migrate_down!(repository_name)
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
# Auto migrates the data-store to match the model
|
167
|
+
#
|
168
|
+
# @param Symbol repository_name the repository to be migrated
|
169
|
+
#
|
170
|
+
# @api private
|
171
|
+
def auto_migrate_up!(repository_name = self.repository_name)
|
172
|
+
assert_valid(true)
|
173
|
+
base_model = self.base_model
|
174
|
+
if base_model == self
|
175
|
+
repository(repository_name).create_model_storage(self)
|
176
|
+
else
|
177
|
+
base_model.auto_migrate_up!(repository_name)
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
end # module Model
|
182
|
+
|
183
|
+
def self.include_migration_api
|
184
|
+
DataMapper.extend(SingletonMethods)
|
185
|
+
[ :Repository, :Model ].each do |name|
|
186
|
+
DataMapper.const_get(name).send(:include, const_get(name))
|
187
|
+
end
|
188
|
+
DataMapper::Model.append_extensions(Model)
|
189
|
+
Adapters::AbstractAdapter.descendants.each do |adapter_class|
|
190
|
+
Adapters.include_migration_api(ActiveSupport::Inflector.demodulize(adapter_class.name))
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
end
|
195
|
+
|
196
|
+
module Adapters
|
197
|
+
|
198
|
+
def self.include_migration_api(const_name)
|
199
|
+
require auto_migration_extensions(const_name)
|
200
|
+
if Migrations.const_defined?(const_name)
|
201
|
+
adapter = const_get(const_name)
|
202
|
+
adapter.send(:include, migration_module(const_name))
|
203
|
+
end
|
204
|
+
rescue LoadError
|
205
|
+
# Silently ignore the fact that no adapter extensions could be required
|
206
|
+
# This means that the adapter in use doesn't support migrations
|
207
|
+
end
|
208
|
+
|
209
|
+
def self.migration_module(const_name)
|
210
|
+
Migrations.const_get(const_name)
|
211
|
+
end
|
212
|
+
|
213
|
+
class << self
|
214
|
+
private
|
215
|
+
|
216
|
+
# @api private
|
217
|
+
def auto_migration_extensions(const_name)
|
218
|
+
name = adapter_name(const_name)
|
219
|
+
name = 'do' if name == 'dataobjects'
|
220
|
+
"dm-migrations/adapters/dm-#{name}-adapter"
|
221
|
+
end
|
222
|
+
|
223
|
+
end
|
224
|
+
|
225
|
+
extendable do
|
226
|
+
# @api private
|
227
|
+
def const_added(const_name)
|
228
|
+
include_migration_api(const_name)
|
229
|
+
super
|
230
|
+
end
|
231
|
+
end
|
232
|
+
|
233
|
+
end # module Adapters
|
234
|
+
|
235
|
+
Migrations.include_migration_api
|
236
|
+
|
237
|
+
end # module DataMapper
|