Module | Sequel::Migrator |
In: |
lib/sequel/extensions/migration.rb
|
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)
DEFAULT_SCHEMA_COLUMN | = | :version |
DEFAULT_SCHEMA_TABLE | = | :schema_info |
MIGRATION_FILE_PATTERN | = | /\A\d+_.+\.rb\z/.freeze |
MIGRATION_SPLITTER | = | '_'.freeze |
Gets the current migration version stored in the database. If no version number is stored, 0 is returned.
# File lib/sequel/extensions/migration.rb, line 175 175: def self.get_current_migration_version(db, opts={}) 176: (schema_info_dataset(db, opts).first || {})[opts[:column] || DEFAULT_SCHEMA_COLUMN] || 0 177: end
Returns the latest version available in the specified directory.
# File lib/sequel/extensions/migration.rb, line 180 180: def self.latest_migration_version(directory) 181: l = migration_files(directory).last 182: l ? migration_version_from_file(File.basename(l)) : nil 183: end
Returns a list of migration classes filtered for the migration range and ordered according to the migration direction.
# File lib/sequel/extensions/migration.rb, line 187 187: def self.migration_classes(directory, target, current, direction) 188: range = direction == :up ? 189: (current + 1)..target : (target + 1)..current 190: 191: # Remove class definitions 192: Migration.descendants.each do |c| 193: Object.send(:remove_const, c.to_s) rescue nil 194: end 195: Migration.descendants.clear # remove any defined migration classes 196: 197: # load migration files 198: migration_files(directory, range).each {|fn| load(fn)} 199: 200: # get migration classes 201: classes = Migration.descendants 202: classes.reverse! if direction == :down 203: classes 204: end
Returns any found migration files in the supplied directory.
# File lib/sequel/extensions/migration.rb, line 207 207: def self.migration_files(directory, range = nil) 208: files = [] 209: Dir.new(directory).each do |file| 210: files[migration_version_from_file(file)] = File.join(directory, file) if MIGRATION_FILE_PATTERN.match(file) 211: end 212: filtered = range ? files[range] : files 213: filtered ? filtered.compact : [] 214: end
Migrates the supplied database using the migration files in the the specified directory. Options:
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)
# File lib/sequel/extensions/migration.rb, line 156 156: def self.run(db, directory, opts={}) 157: raise(Error, "Must supply a valid migration path") unless directory and File.directory?(directory) 158: raise(Error, "No current version available") unless current = opts[:current] || get_current_migration_version(db, opts) 159: raise(Error, "No target version available") unless target = opts[:target] || latest_migration_version(directory) 160: 161: direction = current < target ? :up : :down 162: 163: classes = migration_classes(directory, target, current, direction) 164: 165: db.transaction do 166: classes.each {|c| c.apply(db, direction)} 167: set_current_migration_version(db, target, opts) 168: end 169: 170: target 171: end
Returns the dataset for the schema_info table. If no such table exists, it is automatically created.
# File lib/sequel/extensions/migration.rb, line 218 218: def self.schema_info_dataset(db, opts={}) 219: column = opts[:column] || DEFAULT_SCHEMA_COLUMN 220: table = opts[:table] || DEFAULT_SCHEMA_TABLE 221: db.create_table?(table){Integer column} 222: db.alter_table(table){add_column column, Integer} unless db.from(table).columns.include?(column) 223: db.from(table) 224: end
Sets the current migration version stored in the database.
# File lib/sequel/extensions/migration.rb, line 227 227: def self.set_current_migration_version(db, version, opts={}) 228: column = opts[:column] || DEFAULT_SCHEMA_COLUMN 229: dataset = schema_info_dataset(db, opts) 230: dataset.send(dataset.first ? :update : :insert, column => version) 231: end