module RailsConnector module Migrations class Migrator attr_reader :migrations attr_reader :workspace_lock def initialize @migrations = determine_migrations @migration_store = MigrationStore.instance @workspace_lock = WorkspaceLock.instance validate end def migrate workspace.as_current do runnable.each do |migration| migration.migrate @migration_store.add_version(migration.version) end end end def publish remove_workspace_with do CmsRestApi.put("workspaces/#{workspace.id}/publish", {}) end end def abort remove_workspace_with do CmsRestApi.delete("workspaces/#{workspace.id}") end end private def workspace workspace = migration_workspace if workspace if workspace_lock.exists? workspace_lock.validate(workspace) end else CmsRestApi.post('workspaces', :workspace => { :title => 'rtc', :id => 'rtc' }) workspace = migration_workspace workspace_lock.write(workspace) end workspace end def migration_workspace Workspace.find('rtc') rescue ResourceNotFound end def remove_workspace_with(&block) workspace = migration_workspace if workspace workspace_lock.validate(workspace) yield workspace_lock.remove else raise RailsConnectorError.new('Migration workspace does not exist') end end def determine_migrations files = Dir[*migrations_paths.map { |path| "#{path}/**/[0-9]*_*.rb" }] migrations = files.map do |file| version, name = file.scan(/([0-9]+)_([_a-z0-9]*)\.rb\z/).first unless version raise RailsConnectorError.new("Illegal name for migration file: #{file}\n\t(only lower case letters, numbers, and '_' allowed)") end version = version name = name.camelize require(File.expand_path(file)) name.constantize.new(name, version) end migrations.sort_by(&:version) end def migrations_paths ["#{Rails.root}/cms/migrate"] end def runnable migrations.reject do |migration| migrated_versions.include?(migration.version) end end def migrated_versions @migration_store.versions end def validate name, _ = migrations.group_by(&:name).find { |_, value| value.length > 1 } if name raise RailsConnectorError.new("Multiple migrations have the name #{name}") end version, _ = migrations.group_by(&:version).find { |_, value| value.length > 1 } if version raise RailsConnectorError.new("Multiple migrations have the version number #{version}") end end end end end