Module: Sequel::Migrator
- Defined in:
- lib/sequel/extensions/migration.rb
Overview
The Migrator module performs migrations based on migration files in a specified directory. The migration files should be named using the following pattern (in similar fashion to ActiveRecord migrations):
<version>_<title>.rb
For example, the following files are considered migration files:
001_create_sessions.rb
002_add_data_column.rb
...
The migration files should contain one or more migration classes based on Sequel::Migration.
Migrations are generally run via the sequel command line tool, using the -m and -M switches. The -m switch specifies the migration directory, and the -M switch specifies the version to which to migrate.
You can apply migrations using the Migrator API, as well (this is necessary if you want to specify the version from which to migrate in addition to the version to which to migrate). To apply a migration, the #apply method must be invoked with the database instance, the directory of migration files and the target version. If no current version is supplied, it is read from the database. The migrator automatically creates a schema_info table in the database to keep track of the current migration version. If no migration version is stored in the database, the version is considered to be 0. If no target version is specified, the database is migrated to the latest version available in the migration directory.
For example, to migrate the database to the latest version:
Sequel::Migrator.apply(DB, '.')
To migrate the database from version 1 to version 5:
Sequel::Migrator.apply(DB, '.', 5, 1)
Constant Summary collapse
- DEFAULT_SCHEMA_COLUMN =
:version
- DEFAULT_SCHEMA_TABLE =
:schema_info
- MIGRATION_FILE_PATTERN =
/\A\d+_.+\.rb\z/.freeze
- MIGRATION_SPLITTER =
'_'.freeze
Class Method Summary collapse
-
.apply(db, directory, target = nil, current = nil) ⇒ Object
Wrapper for run, maintaining backwards API compatibility.
-
.get_current_migration_version(db, opts = {}) ⇒ Object
Gets the current migration version stored in the database.
-
.latest_migration_version(directory) ⇒ Object
Returns the latest version available in the specified directory.
-
.migration_classes(directory, target, current, direction) ⇒ Object
Returns a list of migration classes filtered for the migration range and ordered according to the migration direction.
-
.migration_files(directory, range = nil) ⇒ Object
Returns any found migration files in the supplied directory.
-
.run(db, directory, opts = {}) ⇒ Object
Migrates the supplied database using the migration files in the the specified directory.
-
.schema_info_dataset(db, opts = {}) ⇒ Object
Returns the dataset for the schema_info table.
-
.set_current_migration_version(db, version, opts = {}) ⇒ Object
Sets the current migration version stored in the database.
Class Method Details
.apply(db, directory, target = nil, current = nil) ⇒ Object
Wrapper for run, maintaining backwards API compatibility
140 141 142 |
# File 'lib/sequel/extensions/migration.rb', line 140 def self.apply(db, directory, target = nil, current = nil) run(db, directory, :target => target, :current => current) end |
.get_current_migration_version(db, opts = {}) ⇒ Object
Gets the current migration version stored in the database. If no version number is stored, 0 is returned.
175 176 177 |
# File 'lib/sequel/extensions/migration.rb', line 175 def self.get_current_migration_version(db, opts={}) (schema_info_dataset(db, opts).first || {})[opts[:column] || DEFAULT_SCHEMA_COLUMN] || 0 end |
.latest_migration_version(directory) ⇒ Object
Returns the latest version available in the specified directory.
180 181 182 183 |
# File 'lib/sequel/extensions/migration.rb', line 180 def self.latest_migration_version(directory) l = migration_files(directory).last l ? migration_version_from_file(File.basename(l)) : nil end |
.migration_classes(directory, target, current, direction) ⇒ Object
Returns a list of migration classes filtered for the migration range and ordered according to the migration direction.
187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 |
# File 'lib/sequel/extensions/migration.rb', line 187 def self.migration_classes(directory, target, current, direction) range = direction == :up ? (current + 1)..target : (target + 1)..current # Remove class definitions Migration.descendants.each do |c| Object.send(:remove_const, c.to_s) rescue nil end Migration.descendants.clear # remove any defined migration classes # load migration files migration_files(directory, range).each {|fn| load(fn)} # get migration classes classes = Migration.descendants classes.reverse! if direction == :down classes end |
.migration_files(directory, range = nil) ⇒ Object
Returns any found migration files in the supplied directory.
207 208 209 210 211 212 213 214 |
# File 'lib/sequel/extensions/migration.rb', line 207 def self.migration_files(directory, range = nil) files = [] Dir.new(directory).each do |file| files[migration_version_from_file(file)] = File.join(directory, file) if MIGRATION_FILE_PATTERN.match(file) end filtered = range ? files[range] : files filtered ? filtered.compact : [] end |
.run(db, directory, opts = {}) ⇒ Object
Migrates the supplied database using the migration files in the the specified directory. Options:
-
:column - The column in the :table argument storing the migration version (default: :version).
-
:current - The current version of the database. If not given, it is retrieved from the database using the :table and :column options.
-
:table - The table containing the schema version (default: :schema_info).
-
:target - The target version to which to migrate. If not given, migrates to the maximum version.
Examples:
Sequel::Migrator.run(DB, "migrations")
Sequel::Migrator.run(DB, "migrations", :target=>15, :current=>10)
Sequel::Migrator.run(DB, "app1/migrations", :column=> :app2_version)
Sequel::Migrator.run(DB, "app2/migrations", :column => :app2_version, :table=>:schema_info2)
156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 |
# File 'lib/sequel/extensions/migration.rb', line 156 def self.run(db, directory, opts={}) raise(Error, "Must supply a valid migration path") unless directory and File.directory?(directory) raise(Error, "No current version available") unless current = opts[:current] || get_current_migration_version(db, opts) raise(Error, "No target version available") unless target = opts[:target] || latest_migration_version(directory) direction = current < target ? :up : :down classes = migration_classes(directory, target, current, direction) db.transaction do classes.each {|c| c.apply(db, direction)} set_current_migration_version(db, target, opts) end target end |
.schema_info_dataset(db, opts = {}) ⇒ Object
Returns the dataset for the schema_info table. If no such table exists, it is automatically created.
218 219 220 221 222 223 224 |
# File 'lib/sequel/extensions/migration.rb', line 218 def self.schema_info_dataset(db, opts={}) column = opts[:column] || DEFAULT_SCHEMA_COLUMN table = opts[:table] || DEFAULT_SCHEMA_TABLE db.create_table?(table){Integer column} db.alter_table(table){add_column column, Integer} unless db.from(table).columns.include?(column) db.from(table) end |
.set_current_migration_version(db, version, opts = {}) ⇒ Object
Sets the current migration version stored in the database.
227 228 229 230 231 |
# File 'lib/sequel/extensions/migration.rb', line 227 def self.set_current_migration_version(db, version, opts={}) column = opts[:column] || DEFAULT_SCHEMA_COLUMN dataset = schema_info_dataset(db, opts) dataset.send(dataset.first ? :update : :insert, column => version) end |