To check out this repository please hg clone the following URL, or open the URL using EasyMercurial or your preferred Mercurial client.

Statistics Download as Zip
| Branch: | Tag: | Revision:

root / .svn / pristine / 5d / 5dc200a9880b49ee8adf93752f95bd14fc23a33e.svn-base @ 1297:0a574315af3e

History | View | Annotate | Download (3.48 KB)

1
# Generates a migration which migrates all plugins to their latest versions
2
# within the database.
3
class PluginMigrationGenerator < Rails::Generator::Base
4
  
5
  # 255 characters max for Windows NTFS (http://en.wikipedia.org/wiki/Filename)
6
  # minus 14 for timestamp, minus some extra chars for dot, underscore, file 
7
  # extension. So let's have 230.
8
  MAX_FILENAME_LENGTH = 230
9
    
10
  def initialize(runtime_args, runtime_options={})
11
    super
12
    @options = {:assigns => {}}
13
    ensure_schema_table_exists    
14
    get_plugins_to_migrate(runtime_args)
15
    
16
    if @plugins_to_migrate.empty?
17
      puts "All plugins are migrated to their latest versions"
18
      exit(0)
19
    end
20

    
21
    @options[:migration_file_name] = build_migration_name
22
    @options[:assigns][:class_name] = build_migration_name.classify
23
  end
24
  
25
  def manifest
26
    record do |m|
27
      m.migration_template 'plugin_migration.erb', 'db/migrate', @options
28
    end
29
  end
30
  
31
  protected
32

    
33
    # Create the schema table if it doesn't already exist.
34
    def ensure_schema_table_exists
35
      ActiveRecord::Base.connection.initialize_schema_migrations_table
36
    end
37

    
38
    # Determine all the plugins which have migrations that aren't present
39
    # according to the plugin schema information from the database.
40
    def get_plugins_to_migrate(plugin_names)
41

    
42
      # First, grab all the plugins which exist and have migrations
43
      @plugins_to_migrate = if plugin_names.empty?
44
        Engines.plugins
45
      else
46
        plugin_names.map do |name| 
47
          Engines.plugins[name] ? Engines.plugins[name] : raise("Cannot find the plugin '#{name}'")
48
        end
49
      end
50
      
51
      @plugins_to_migrate.reject! { |p| !p.respond_to?(:latest_migration) || p.latest_migration.nil? }
52
      
53
      # Then find the current versions from the database    
54
      @current_versions = {}
55
      @plugins_to_migrate.each do |plugin|
56
        @current_versions[plugin.name] = Engines::Plugin::Migrator.current_version(plugin)
57
      end
58

    
59
      # Then find the latest versions from their migration directories
60
      @new_versions = {}      
61
      @plugins_to_migrate.each do |plugin|
62
        @new_versions[plugin.name] = plugin.latest_migration
63
      end
64
      
65
      # Remove any plugins that don't need migration
66
      @plugins_to_migrate.map { |p| p.name }.each do |name|
67
        @plugins_to_migrate.delete(Engines.plugins[name]) if @current_versions[name] == @new_versions[name]
68
      end
69
      
70
      @options[:assigns][:plugins] = @plugins_to_migrate
71
      @options[:assigns][:new_versions] = @new_versions
72
      @options[:assigns][:current_versions] = @current_versions
73
    end
74

    
75
    # Returns a migration name. If the descriptive migration name based on the 
76
    # plugin names involved is shorter than 230 characters that one will be
77
    # used. Otherwise a shorter name will be returned.
78
    def build_migration_name
79
      descriptive_migration_name.tap do |name|        
80
        name.replace short_migration_name if name.length > MAX_FILENAME_LENGTH
81
      end
82
    end
83

    
84
    # Construct a unique migration name based on the plugins involved and the
85
    # versions they should reach after this migration is run. The name constructed
86
    # needs to be lowercase
87
    def descriptive_migration_name
88
      @plugins_to_migrate.map do |plugin| 
89
        "#{plugin.name}_to_version_#{@new_versions[plugin.name]}" 
90
      end.join("_and_").downcase
91
    end
92

    
93
    # Short migration name that will be used if the descriptive_migration_name
94
    # exceeds 230 characters
95
    def short_migration_name
96
      'plugin_migrations'
97
    end
98
end