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 704 def initialize(db, directory, opts=OPTS) 705 super 706 @target = opts[:target] 707 @applied_migrations = get_applied_migrations 708 @migration_tuples = get_migration_tuples 709 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 714 def self.run_single(db, path, opts=OPTS) 715 new(db, File.dirname(path), opts).run_single(path, opts[:direction] || :up) 716 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 720 def is_current? 721 migration_tuples.empty? 722 end
Apply all migration tuples on the database
# File lib/sequel/extensions/migration.rb 725 def run 726 migration_tuples.each do |m, f, direction| 727 apply_migration(m, f, direction) 728 end 729 nil 730 end
Apply single migration tuple at the given path with the given direction on the database.
# File lib/sequel/extensions/migration.rb 734 def run_single(path, direction) 735 migration = load_migration_file(path) 736 file_name = File.basename(path) 737 already_applied = applied_migrations.include?(file_name.downcase) 738 739 return if direction == :up ? already_applied : !already_applied 740 741 apply_migration(migration, file_name, direction) 742 nil 743 end
Private Instance Methods
Apply a single migration with the given filename in the given direction.
# File lib/sequel/extensions/migration.rb 748 def apply_migration(migration, file_name, direction) 749 fi = file_name.downcase 750 t = Time.now 751 752 db.log_info("Begin applying migration #{file_name}, direction: #{direction}") 753 checked_transaction(migration) do 754 migration.apply(db, direction) 755 direction == :up ? ds.insert(column=>fi) : ds.where(column=>fi).delete 756 end 757 db.log_info("Finished applying migration #{file_name}, direction: #{direction}, took #{sprintf('%0.6f', Time.now - t)} seconds") 758 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 762 def convert_from_schema_info 763 v = db[:schema_info].get(:version) 764 ds = db.from(table) 765 files.each do |path| 766 f = File.basename(path) 767 if migration_version_from_file(f) <= v 768 ds.insert(column=>f) 769 end 770 end 771 end
The default column storing migration filenames.
# File lib/sequel/extensions/migration.rb 774 def default_schema_column 775 :filename 776 end
The default table storing migration filenames.
# File lib/sequel/extensions/migration.rb 779 def default_schema_table 780 :schema_migrations 781 end
Returns filenames of all applied migrations
# File lib/sequel/extensions/migration.rb 784 def get_applied_migrations 785 am = ds.select_order_map(column) 786 missing_migration_files = am - files.map{|f| File.basename(f).downcase} 787 raise(Error, "Applied migration files not in file system: #{missing_migration_files.join(', ')}") if missing_migration_files.length > 0 && !@allow_missing_migration_files 788 am 789 end
Returns any migration files found in the migrator’s directory.
# File lib/sequel/extensions/migration.rb 792 def get_migration_files 793 files = [] 794 Dir.new(directory).each do |file| 795 next unless MIGRATION_FILE_PATTERN.match(file) 796 files << File.join(directory, file) 797 end 798 files.sort! do |a, b| 799 a_ver, a_name = split_migration_filename(a) 800 b_ver, b_name = split_migration_filename(b) 801 x = a_ver <=> b_ver 802 if x.zero? 803 x = a_name <=> b_name 804 end 805 x 806 end 807 files 808 end
Returns tuples of migration, filename, and direction
# File lib/sequel/extensions/migration.rb 818 def get_migration_tuples 819 up_mts = [] 820 down_mts = [] 821 files.each do |path| 822 f = File.basename(path) 823 fi = f.downcase 824 if target 825 if migration_version_from_file(f) > target 826 if applied_migrations.include?(fi) 827 down_mts << [load_migration_file(path), f, :down] 828 end 829 elsif !applied_migrations.include?(fi) 830 up_mts << [load_migration_file(path), f, :up] 831 end 832 elsif !applied_migrations.include?(fi) 833 up_mts << [load_migration_file(path), f, :up] 834 end 835 end 836 up_mts + down_mts.reverse 837 end
Returns the dataset for the schema_migrations table. If no such table exists, it is automatically created.
# File lib/sequel/extensions/migration.rb 841 def schema_dataset 842 c = column 843 ds = db.from(table) 844 if !db.table_exists?(table) 845 begin 846 db.create_table(table){String c, :primary_key=>true} 847 rescue Sequel::DatabaseError => e 848 if db.database_type == :mysql && e.message.include?('max key length') 849 # Handle case where MySQL is used with utf8mb4 charset default, which 850 # only allows a maximum length of about 190 characters for string 851 # primary keys due to InnoDB limitations. 852 db.create_table(table){String c, :primary_key=>true, :size=>190} 853 else 854 raise e 855 end 856 end 857 if db.table_exists?(:schema_info) and vha = db[:schema_info].all and vha.length == 1 and 858 vha.first.keys == [:version] and vha.first.values.first.is_a?(Integer) 859 convert_from_schema_info 860 end 861 elsif !ds.columns.include?(c) 862 raise(Error, "Migrator table #{table} does not contain column #{c}") 863 end 864 ds 865 end
Return an integer and name (without extension) for the given path.
# File lib/sequel/extensions/migration.rb 811 def split_migration_filename(path) 812 version, name = MIGRATION_FILE_PATTERN.match(File.basename(path)).captures 813 version = version.to_i 814 [version, name] 815 end