Class: Sequel::Migrator
Overview
The Migrator class performs migrations based on migration files in a
specified directory. The migration files should be named using the
following pattern:
<version>_<title>.rb
For example, the following files are considered migration files:
001_create_sessions.rb
002_add_data_column.rb
You can also use timestamps as version numbers:
1273253850_create_sessions.rb
1273257248_add_data_column.rb
If any migration filenames use timestamps as version numbers, Sequel
uses the TimestampMigrator to migrate, otherwise it uses the IntegerMigrator.
The TimestampMigrator can handle migrations that are run out of order
as well as migrations with the same timestamp,
while the IntegerMigrator is more strict and raises exceptions for missing
or duplicate migration files.
The migration files should contain either one Migration
subclass or one Sequel.migration call.
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 migrator, 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 table (schema_info for integer migrations and
schema_migrations for timestamped migrations). 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, or the target version specified is greater than the latest
version available, 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.run(DB, '.')
For example, to migrate the database all the way down:
Sequel::Migrator.run(DB, '.', target: 0)
For example, to migrate the database to version 4:
Sequel::Migrator.run(DB, '.', target: 4)
To migrate the database from version 1 to version 5:
Sequel::Migrator.run(DB, '.', target: 5, current: 1)
Part of the migration extension.
Direct Known Subclasses
Defined Under Namespace
Classes: Error, NotCurrentError
Constant Summary collapse
- MIGRATION_FILE_PATTERN =
/\A(\d+)_(.+)\.rb\z/i.freeze
- MUTEX =
Mutex used around migration file loading
Mutex.new
Instance Attribute Summary collapse
-
#column ⇒ Object
readonly
The column to use to hold the migration version number for integer migrations or filename for timestamp migrations (defaults to :version for integer migrations and :filename for timestamp migrations).
-
#db ⇒ Object
readonly
The database related to this migrator.
-
#directory ⇒ Object
readonly
The directory for this migrator's files.
-
#ds ⇒ Object
readonly
The dataset for this migrator, representing the
schema_infotable for integer migrations and theschema_migrationstable for timestamp migrations. -
#files ⇒ Object
readonly
All migration files in this migrator's directory.
-
#table ⇒ Object
readonly
The table to use to hold the applied migration data (defaults to :schema_info for integer migrations and :schema_migrations for timestamp migrations).
-
#target ⇒ Object
readonly
The target version for this migrator.
Class Method Summary collapse
-
.apply(db, directory, target = nil, current = nil) ⇒ Object
Wrapper for
run, maintaining backwards API compatibility. -
.check_current(*args) ⇒ Object
Raise a NotCurrentError unless the migrator is current, takes the same arguments as #run.
-
.is_current?(db, directory, opts = OPTS) ⇒ Boolean
Return whether the migrator is current (i.e. it does not need to make any changes).
-
.migrator_class(directory) ⇒ Object
Choose the Migrator subclass to use.
-
.run(db, directory, opts = OPTS) ⇒ Object
Migrates the supplied database using the migration files in the specified directory.
Instance Method Summary collapse
-
#initialize(db, directory, opts = OPTS) ⇒ Migrator
constructor
Setup the state for the migrator.
Constructor Details
#initialize(db, directory, opts = OPTS) ⇒ Migrator
Setup the state for the migrator
487 488 489 490 491 492 493 494 495 496 497 498 |
# File 'lib/sequel/extensions/migration.rb', line 487 def initialize(db, directory, opts=OPTS) raise(Error, "Must supply a valid migration path") unless File.directory?(directory) @db = db @directory = directory @allow_missing_migration_files = opts[:allow_missing_migration_files] @files = get_migration_files schema, table = @db.send(:schema_and_table, opts[:table] || default_schema_table) @table = schema ? Sequel::SQL::QualifiedIdentifier.new(schema, table) : table @column = opts[:column] || default_schema_column @ds = schema_dataset @use_transactions = opts[:use_transactions] end |
Instance Attribute Details
#column ⇒ Object (readonly)
The column to use to hold the migration version number for integer migrations or filename for timestamp migrations (defaults to :version for integer migrations and :filename for timestamp migrations)
464 465 466 |
# File 'lib/sequel/extensions/migration.rb', line 464 def column @column end |
#db ⇒ Object (readonly)
The database related to this migrator
467 468 469 |
# File 'lib/sequel/extensions/migration.rb', line 467 def db @db end |
#directory ⇒ Object (readonly)
The directory for this migrator's files
470 471 472 |
# File 'lib/sequel/extensions/migration.rb', line 470 def directory @directory end |
#ds ⇒ Object (readonly)
The dataset for this migrator, representing the schema_info table for integer
migrations and the schema_migrations table for timestamp migrations
474 475 476 |
# File 'lib/sequel/extensions/migration.rb', line 474 def ds @ds end |
#files ⇒ Object (readonly)
All migration files in this migrator's directory
477 478 479 |
# File 'lib/sequel/extensions/migration.rb', line 477 def files @files end |
#table ⇒ Object (readonly)
The table to use to hold the applied migration data (defaults to :schema_info for integer migrations and :schema_migrations for timestamp migrations)
481 482 483 |
# File 'lib/sequel/extensions/migration.rb', line 481 def table @table end |
#target ⇒ Object (readonly)
The target version for this migrator
484 485 486 |
# File 'lib/sequel/extensions/migration.rb', line 484 def target @target end |
Class Method Details
.apply(db, directory, target = nil, current = nil) ⇒ Object
Wrapper for run, maintaining backwards API compatibility
391 392 393 |
# File 'lib/sequel/extensions/migration.rb', line 391 def self.apply(db, directory, target = nil, current = nil) run(db, directory, :target => target, :current => current) end |
.check_current(*args) ⇒ Object
Raise a NotCurrentError unless the migrator is current, takes the same arguments as #run.
397 398 399 |
# File 'lib/sequel/extensions/migration.rb', line 397 def self.check_current(*args) raise(NotCurrentError, 'current migration version does not match latest available version') unless is_current?(*args) end |
.is_current?(db, directory, opts = OPTS) ⇒ Boolean
Return whether the migrator is current (i.e. it does not need to make any changes). Takes the same arguments as #run.
403 404 405 |
# File 'lib/sequel/extensions/migration.rb', line 403 def self.is_current?(db, directory, opts=OPTS) migrator_class(directory).new(db, directory, opts).is_current? end |
.migrator_class(directory) ⇒ Object
Choose the Migrator subclass to use. Uses the TimestampMigrator if the version number is greater than 20000101, otherwise uses the IntegerMigrator.
448 449 450 451 452 453 454 455 456 457 458 459 |
# File 'lib/sequel/extensions/migration.rb', line 448 def self.migrator_class(directory) if self.equal?(Migrator) raise(Error, "Must supply a valid migration path") unless File.directory?(directory) Dir.new(directory).each do |file| next unless MIGRATION_FILE_PATTERN.match(file) return TimestampMigrator if file.split('_', 2).first.to_i > 20000101 end IntegerMigrator else self end end |
.run(db, directory, opts = OPTS) ⇒ Object
Migrates the supplied database using the migration files in the specified directory. Options: :allow_migration_number :: Set to check each migration number. If set, calls the === method on the object with the migration number, allowing it to work with both ranges and procs. If the === method returns false, an exception is raised (TimestampMigrator only). :allow_missing_migration_files :: Don't raise an error if there are missing migration files. It is very risky to use this option, since it can result in the database schema version number not matching the expected database schema. :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. :relative :: Run the given number of migrations, with a positive number being migrations to migrate up, and a negative number being migrations to migrate down (IntegerMigrator only). :table :: The table containing the schema version (default: :schema_info for integer migrations and :schema_migrations for timestamped migrations). :target :: The target version to which to migrate. If not given, migrates to the maximum version. :use_advisory_lock :: Use advisory locks in migrations (only use this if Sequel supports advisory locks for the database).
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)
438 439 440 441 442 443 444 |
# File 'lib/sequel/extensions/migration.rb', line 438 def self.run(db, directory, opts=OPTS) if opts[:use_advisory_lock] db.with_advisory_lock(MIGRATION_ADVISORY_LOCK_ID){run(db, directory, opts.merge(:use_advisory_lock=>false))} else migrator_class(directory).new(db, directory, opts).run end end |