Class: MongoMapper::Migrator

Inherits:
Object
  • Object
show all
Defined in:
lib/mongo_mapper/migrator.rb

Overview

:nodoc:

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(direction, migrations_path, target_version = nil) ⇒ Migrator

Returns a new instance of Migrator.



48
49
50
# File 'lib/mongo_mapper/migrator.rb', line 48

def initialize(direction, migrations_path, target_version = nil)
  @direction, @migrations_path, @target_version = direction, migrations_path, target_version      
end

Class Method Details

.current_versionObject



38
39
40
# File 'lib/mongo_mapper/migrator.rb', line 38

def current_version
  get_all_versions.max || 0
end

.down(migrations_path, target_version = nil) ⇒ Object



26
27
28
# File 'lib/mongo_mapper/migrator.rb', line 26

def down(migrations_path, target_version = nil)
  self.new(:down, migrations_path, target_version).migrate
end

.get_all_versionsObject



34
35
36
# File 'lib/mongo_mapper/migrator.rb', line 34

def get_all_versions
  MongoMapper::SchemaMigration.all.map{|sm| sm.version.to_i}.sort
end

.migrate(migrations_path, target_version = nil) ⇒ Object



4
5
6
7
8
9
10
# File 'lib/mongo_mapper/migrator.rb', line 4

def migrate(migrations_path, target_version = nil)
  case
    when target_version.nil?              then up(migrations_path, target_version)
    when current_version > target_version then down(migrations_path, target_version)
    else                                       up(migrations_path, target_version)
  end
end

.proper_table_name(name) ⇒ Object



42
43
44
45
# File 'lib/mongo_mapper/migrator.rb', line 42

def proper_table_name(name)
  # Use the Active Record objects own table_name, or pre/suffix from MongoMapper::Base if name is a symbol/string
  name.table_name rescue "#{MongoMapper::Base.table_name_prefix}#{name}#{MongoMapper::Base.table_name_suffix}"
end

.rollback(migrations_path, steps = 1) ⇒ Object



12
13
14
15
16
17
18
19
20
# File 'lib/mongo_mapper/migrator.rb', line 12

def rollback(migrations_path, steps=1)
  migrator = self.new(:down, migrations_path)
  start_index = migrator.migrations.index(migrator.current_migration)
  
  return unless start_index
  
  finish = migrator.migrations[start_index + steps]
  down(migrations_path, finish ? finish.version : 0)
end

.run(direction, migrations_path, target_version) ⇒ Object



30
31
32
# File 'lib/mongo_mapper/migrator.rb', line 30

def run(direction, migrations_path, target_version)
  self.new(direction, migrations_path, target_version).run
end

.up(migrations_path, target_version = nil) ⇒ Object



22
23
24
# File 'lib/mongo_mapper/migrator.rb', line 22

def up(migrations_path, target_version = nil)
  self.new(:up, migrations_path, target_version).migrate
end

Instance Method Details

#current_migrationObject



56
57
58
# File 'lib/mongo_mapper/migrator.rb', line 56

def current_migration
  migrations.detect { |m| m.version == current_version }
end

#current_versionObject



52
53
54
# File 'lib/mongo_mapper/migrator.rb', line 52

def current_version
  migrated.last || 0
end

#migrateObject



69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
# File 'lib/mongo_mapper/migrator.rb', line 69

def migrate
  current = migrations.detect { |m| m.version == current_version }
  target = migrations.detect { |m| m.version == @target_version }

  if target.nil? && !@target_version.nil? && @target_version > 0
    raise UnknownMigrationVersionError.new(@target_version)
  end
  
  start = up? ? 0 : (migrations.index(current) || 0)
  finish = migrations.index(target) || migrations.size - 1
  runnable = migrations[start..finish]
  
  # skip the last migration if we're headed down, but not ALL the way down
  runnable.pop if down? && !target.nil?
  
  runnable.each do |migration|
    # On our way up, we skip migrating the ones we've already migrated
    next if up? && migrated.include?(migration.version.to_i)

    # On our way down, we skip reverting the ones we've never migrated
    if down? && !migrated.include?(migration.version.to_i)
      migration.announce 'never migrated, skipping'; migration.write
      next
    end

    migration.migrate(@direction)
    record_version_state_after_migrating(migration.version)
  end
end

#migratedObject



134
135
136
# File 'lib/mongo_mapper/migrator.rb', line 134

def migrated
  @migrated_versions ||= self.class.get_all_versions
end

#migrationsObject



99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
# File 'lib/mongo_mapper/migrator.rb', line 99

def migrations
  @migrations ||= begin
    files = Dir["#{@migrations_path}/[0-9]*_*.rb"]
    
    migrations = files.inject([]) do |klasses, file|
      version, name = file.scan(/([0-9]+)_([_a-z0-9]*).rb/).first
      
      raise IllegalMigrationNameError.new(file) unless version
      version = version.to_i
      
      if klasses.detect { |m| m.version == version }
        raise DuplicateMigrationVersionError.new(version) 
      end

      if klasses.detect { |m| m.name == name.camelize }
        raise DuplicateMigrationNameError.new(name.camelize) 
      end
      
      klasses << returning(MigrationProxy.new) do |migration|
        migration.name     = name.camelize
        migration.version  = version
        migration.filename = file
      end
    end
    
    migrations = migrations.sort_by(&:version)
    down? ? migrations.reverse : migrations
  end
end

#pending_migrationsObject



129
130
131
132
# File 'lib/mongo_mapper/migrator.rb', line 129

def pending_migrations
  already_migrated = migrated
  migrations.reject { |m| already_migrated.include?(m.version.to_i) }
end

#runObject

Raises:



60
61
62
63
64
65
66
67
# File 'lib/mongo_mapper/migrator.rb', line 60

def run
  target = migrations.detect { |m| m.version == @target_version }
  raise UnknownMigrationVersionError.new(@target_version) if target.nil?
  unless (up? && migrated.include?(target.version.to_i)) || (down? && !migrated.include?(target.version.to_i))
    target.migrate(@direction)
    record_version_state_after_migrating(target.version)
  end
end