class Sequel::TimestampMigrator
The migrator used if any migration file version is greater than 20000101.
Stores filenames of migration files, and can figure out which migrations
have not been applied and apply them, even if earlier migrations are added
after later migrations. If you plan to do that, the responsibility is on
you to make sure the migrations don't conflict. Part of the
migration
extension.
Constants
- Error
Attributes
Array of strings of applied migration filenames
Get tuples of migrations, filenames, and actions for each migration
Public Class Methods
Set up all state for the migrator instance
# File lib/sequel/extensions/migration.rb, line 699 def initialize(db, directory, opts=OPTS) super @target = opts[:target] @applied_migrations = get_applied_migrations @migration_tuples = get_migration_tuples end
Apply the migration in the given file path. See Sequel::Migrator.run for the available options. Additionally, this method supports the :direction option for whether to run the migration up (default) or down.
# File lib/sequel/extensions/migration.rb, line 709 def self.run_single(db, path, opts=OPTS) new(db, File.dirname(path), opts).run_single(path, opts[:direction] || :up) end
Public Instance Methods
The timestamp migrator is current if there are no migrations to apply in either direction.
# File lib/sequel/extensions/migration.rb, line 715 def is_current? migration_tuples.empty? end
Apply all migration tuples on the database
# File lib/sequel/extensions/migration.rb, line 720 def run migration_tuples.each do |m, f, direction| apply_migration(m, f, direction) end nil end
Apply single migration tuple at the given path with the given direction on the database.
# File lib/sequel/extensions/migration.rb, line 729 def run_single(path, direction) migration = load_migration_file(path) file_name = File.basename(path) already_applied = applied_migrations.include?(file_name.downcase) return if direction == :up ? already_applied : !already_applied apply_migration(migration, file_name, direction) nil end
Private Instance Methods
Apply a single migration with the given filename in the given direction.
# File lib/sequel/extensions/migration.rb, line 743 def apply_migration(migration, file_name, direction) fi = file_name.downcase t = Time.now db.log_info("Begin applying migration #{file_name}, direction: #{direction}") checked_transaction(migration) do migration.apply(db, direction) direction == :up ? ds.insert(column=>fi) : ds.where(column=>fi).delete end db.log_info("Finished applying migration #{file_name}, direction: #{direction}, took #{sprintf('%0.6f', Time.now - t)} seconds") end
Convert the schema_info table to the new schema_migrations table format, using the version of the schema_info table and the current migration files.
# File lib/sequel/extensions/migration.rb, line 757 def convert_from_schema_info v = db[:schema_info].get(:version) ds = db.from(table) files.each do |path| f = File.basename(path) if migration_version_from_file(f) <= v ds.insert(column=>f) end end end
The default column storing migration filenames.
# File lib/sequel/extensions/migration.rb, line 769 def default_schema_column :filename end
The default table storing migration filenames.
# File lib/sequel/extensions/migration.rb, line 774 def default_schema_table :schema_migrations end
Returns filenames of all applied migrations
# File lib/sequel/extensions/migration.rb, line 779 def get_applied_migrations am = ds.select_order_map(column) missing_migration_files = am - files.map{|f| File.basename(f).downcase} raise(Error, "Applied migration files not in file system: #{missing_migration_files.join(', ')}") if missing_migration_files.length > 0 && !@allow_missing_migration_files am end
Returns any migration files found in the migrator's directory.
# File lib/sequel/extensions/migration.rb, line 787 def get_migration_files files = [] Dir.new(directory).each do |file| next unless MIGRATION_FILE_PATTERN.match(file) files << File.join(directory, file) end files.sort_by{|f| MIGRATION_FILE_PATTERN.match(File.basename(f))[1].to_i} end
Returns tuples of migration, filename, and direction
# File lib/sequel/extensions/migration.rb, line 797 def get_migration_tuples up_mts = [] down_mts = [] files.each do |path| f = File.basename(path) fi = f.downcase if target if migration_version_from_file(f) > target if applied_migrations.include?(fi) down_mts << [load_migration_file(path), f, :down] end elsif !applied_migrations.include?(fi) up_mts << [load_migration_file(path), f, :up] end elsif !applied_migrations.include?(fi) up_mts << [load_migration_file(path), f, :up] end end up_mts + down_mts.reverse end
Returns the dataset for the schema_migrations table. If no such table exists, it is automatically created.
# File lib/sequel/extensions/migration.rb, line 820 def schema_dataset c = column ds = db.from(table) if !db.table_exists?(table) begin db.create_table(table){String c, :primary_key=>true} rescue Sequel::DatabaseError => e if db.database_type == :mysql && e.message =~ /max key length/ # Handle case where MySQL is used with utf8mb4 charset default, which # only allows a maximum length of about 190 characters for string # primary keys due to InnoDB limitations. db.create_table(table){String c, :primary_key=>true, :size=>190} else raise e end end if db.table_exists?(:schema_info) and vha = db[:schema_info].all and vha.length == 1 and vha.first.keys == [:version] and vha.first.values.first.is_a?(Integer) convert_from_schema_info end elsif !ds.columns.include?(c) raise(Error, "Migrator table #{table} does not contain column #{c}") end ds end