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
Sequel::Migrator::new
# File lib/sequel/extensions/migration.rb 689 def initialize(db, directory, opts=OPTS) 690 super 691 @target = opts[:target] 692 @applied_migrations = get_applied_migrations 693 @migration_tuples = get_migration_tuples 694 end
Apply the migration in the given file path. See 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 699 def self.run_single(db, path, opts=OPTS) 700 new(db, File.dirname(path), opts).run_single(path, opts[:direction] || :up) 701 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 705 def is_current? 706 migration_tuples.empty? 707 end
Apply all migration tuples on the database
# File lib/sequel/extensions/migration.rb 710 def run 711 migration_tuples.each do |m, f, direction| 712 apply_migration(m, f, direction) 713 end 714 nil 715 end
Apply single migration tuple at the given path with the given direction on the database.
# File lib/sequel/extensions/migration.rb 719 def run_single(path, direction) 720 migration = load_migration_file(path) 721 file_name = File.basename(path) 722 already_applied = applied_migrations.include?(file_name.downcase) 723 724 return if direction == :up ? already_applied : !already_applied 725 726 apply_migration(migration, file_name, direction) 727 nil 728 end
Private Instance Methods
Apply a single migration with the given filename in the given direction.
# File lib/sequel/extensions/migration.rb 733 def apply_migration(migration, file_name, direction) 734 fi = file_name.downcase 735 t = Time.now 736 737 db.log_info("Begin applying migration #{file_name}, direction: #{direction}") 738 checked_transaction(migration) do 739 migration.apply(db, direction) 740 direction == :up ? ds.insert(column=>fi) : ds.where(column=>fi).delete 741 end 742 db.log_info("Finished applying migration #{file_name}, direction: #{direction}, took #{sprintf('%0.6f', Time.now - t)} seconds") 743 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 747 def convert_from_schema_info 748 v = db[:schema_info].get(:version) 749 ds = db.from(table) 750 files.each do |path| 751 f = File.basename(path) 752 if migration_version_from_file(f) <= v 753 ds.insert(column=>f) 754 end 755 end 756 end
The default column storing migration filenames.
# File lib/sequel/extensions/migration.rb 759 def default_schema_column 760 :filename 761 end
The default table storing migration filenames.
# File lib/sequel/extensions/migration.rb 764 def default_schema_table 765 :schema_migrations 766 end
Returns filenames of all applied migrations
# File lib/sequel/extensions/migration.rb 769 def get_applied_migrations 770 am = ds.select_order_map(column) 771 missing_migration_files = am - files.map{|f| File.basename(f).downcase} 772 raise(Error, "Applied migration files not in file system: #{missing_migration_files.join(', ')}") if missing_migration_files.length > 0 && !@allow_missing_migration_files 773 am 774 end
Returns any migration files found in the migrator's directory.
# File lib/sequel/extensions/migration.rb 777 def get_migration_files 778 files = [] 779 Dir.new(directory).each do |file| 780 next unless MIGRATION_FILE_PATTERN.match(file) 781 files << File.join(directory, file) 782 end 783 files.sort_by{|f| MIGRATION_FILE_PATTERN.match(File.basename(f))[1].to_i} 784 end
Returns tuples of migration, filename, and direction
# File lib/sequel/extensions/migration.rb 787 def get_migration_tuples 788 up_mts = [] 789 down_mts = [] 790 files.each do |path| 791 f = File.basename(path) 792 fi = f.downcase 793 if target 794 if migration_version_from_file(f) > target 795 if applied_migrations.include?(fi) 796 down_mts << [load_migration_file(path), f, :down] 797 end 798 elsif !applied_migrations.include?(fi) 799 up_mts << [load_migration_file(path), f, :up] 800 end 801 elsif !applied_migrations.include?(fi) 802 up_mts << [load_migration_file(path), f, :up] 803 end 804 end 805 up_mts + down_mts.reverse 806 end
Returns the dataset for the schema_migrations table. If no such table exists, it is automatically created.
# File lib/sequel/extensions/migration.rb 810 def schema_dataset 811 c = column 812 ds = db.from(table) 813 if !db.table_exists?(table) 814 begin 815 db.create_table(table){String c, :primary_key=>true} 816 rescue Sequel::DatabaseError => e 817 if db.database_type == :mysql && e.message =~ /max key length/ 818 # Handle case where MySQL is used with utf8mb4 charset default, which 819 # only allows a maximum length of about 190 characters for string 820 # primary keys due to InnoDB limitations. 821 db.create_table(table){String c, :primary_key=>true, :size=>190} 822 else 823 raise e 824 end 825 end 826 if db.table_exists?(:schema_info) and vha = db[:schema_info].all and vha.length == 1 and 827 vha.first.keys == [:version] and vha.first.values.first.is_a?(Integer) 828 convert_from_schema_info 829 end 830 elsif !ds.columns.include?(c) 831 raise(Error, "Migrator table #{table} does not contain column #{c}") 832 end 833 ds 834 end