public
Description: Ruby on Rails plugin to provide notification when you need to run migrations
Homepage: http://blog.hasmanythrough.com/2008/3/2/migration-concordance
Clone URL: git://github.com/joshsusser/migration_concordance.git
joshsusser (author)
Sat Apr 05 11:31:22 -0700 2008
commit  c30cebe19ee9fd63f4b5396abe6ec1ad1a366f3b
tree    12144d2dff32fc0d4908ba185428d2c661f0db73
parent  8ae4eb7e7cdadab3112e411969d2821cf2befc24 parent  5c0f25378cff8019ed3b761508a3cfbc1e08e0e8
migration_concordance / lib / migration_concordance.rb
100644 83 lines (73 sloc) 2.558 kb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
require 'digest/md5'
 
begin
  require 'redgreen'
  mc_use_color = true
rescue LoadError
  mc_use_color = false
end
 
if mc_use_color && !ENV['TM_MODE']
  def mc_red(str); Color.red(str); end
  def mc_green(str); Color.green(str); end
  def mc_yellow(str); Color.yellow(str); end
else
  def mc_red(str); str; end
  def mc_green(str); str; end
  def mc_yellow(str); str; end
end
 
module ActiveRecord
  class Migrator
    class << self
 
      def check_concordance
        case differs = self.current_differs_from_snapshot(File.join(RAILS_ROOT,'db','migrate'))
        when false
          mc_green("***** DB schema is in sync with migrations.")
        when 0
          mc_yellow("***** DB schema state unknown. No migration snapshot to compare.")
        else
          changed = differs.split("_").first.to_i
          current = current_version rescue 0
          if changed <= current
            mc_red("***** DB schema needs to be re-migrated from: #{differs}")
          else
            mc_red("***** DB schema has new migrations - run 'rake db:migrate'")
          end
        end
      end
 
      def migrate_with_snapshot(migrations_path, target_version = nil)
        if migrations_path =~ %r{vendor/plugins}
          migrate_without_snapshot(migrations_path, target_version)
        else
          old_version = current_version rescue nil
          migrate_without_snapshot(migrations_path, target_version)
          if current_version != old_version
            snapshot = generate_snapshot(migrations_path)
            lines = YAML.dump(snapshot).split("\n").sort
            File.open(snapshot_path, "w") { |f| f.puts(lines) }
          end
        end
      end
      alias_method_chain :migrate, :snapshot
 
      def current_differs_from_snapshot(migrations_path)
        if File.exists?(snapshot_path)
          current = generate_snapshot(migrations_path)
          snapshot = YAML.load_file(snapshot_path)
          diff = current.diff(snapshot)
          diff.keys.empty? ? false : diff.keys.sort.first
        else
          0
        end
      end
 
      def generate_snapshot(migrations_path)
        files = Dir[File.join(migrations_path, "[0-9]*_*.rb")].collect { |n| File.basename(n) }
        snapshot = {}
        files.each do |file|
          snapshot[File.basename(file, ".rb")] = Digest::MD5.hexdigest(File.read(File.join(migrations_path, file)))
        end
        snapshot
      end
 
      def snapshot_path
        File.join(RAILS_ROOT, "db", "migration_snapshot.yml")
      end
 
    end
  end
end