Module: Migraine::Generator

Included in:
Migration
Defined in:
lib/migraine/generator.rb

Overview

Module containing schema generators for different database adapters. To add support for a new adapter, simply add a method such as ‘database_schema_for_<adapter>`. The method should return a Hash containing table and column hierarchy, as follows:

{

'table' => ['one_column', 'another_column'],
'another_table' => ['one_column']

}

Instance Method Summary collapse

Instance Method Details

#database_schema_for(uri) ⇒ Object

Fetches names of all tables and columns at specified URI (‘@source` or `@destination`) and returns them neatly organized hierarchically in an array.

‘mysql://root:root@localhost/myproj’.

Parameters:

  • Database (String)

    connection string, e.g.



70
71
72
73
# File 'lib/migraine/generator.rb', line 70

def database_schema_for(uri)
  adapter = uri.split(':')[0]
  send("database_schema_for_#{adapter}", uri)
end

#database_schema_for_mysql(uri) ⇒ Object

Generates a database schema for a MySQL database using the available connections/instance variables. We do this by peeking into the information_schema database.

‘mysql://root:root@localhost/myproj’.

Parameters:

  • Database (String)

    connection string, e.g.



81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
# File 'lib/migraine/generator.rb', line 81

def database_schema_for_mysql(uri)
  user_and_db = uri.split('://')[1]
  user_and_host = user_and_db.split('/')[0]
  source_db = user_and_db.split('/')[1]
  schema = {}

  db = Sequel.connect('mysql://' + user_and_host + '/information_schema')
  db[:tables].
    filter(table_schema: source_db).select(:table_name).
    all.each do |record|
      table = record[:table_name]

      columns = db[:columns].
        filter(table_schema: source_db, table_name: table).
        select(:column_name).all.map { |record| record[:column_name] }

      schema.merge!({ table => columns })
    end
  
  schema
end

#generate(file) ⇒ Object

Generates a new migration file template by analyzing the source and destination connections, saving it to the location specified in the argument. This makes it easy to create migration files where you can fill in destination tables/columns instead of writing it all by hand.

TODO: Factor out any dependencies on instance variables such as @source_connection and @destination_connection.

Parameters:

  • Relative (String)

    path to file.



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
# File 'lib/migraine/generator.rb', line 23

def generate(file)
  connect
  src = @source_connection
  dest = @destination_connection
  path = File.join(Dir.pwd, File.dirname($0), file)

  File.open(path, 'w') do |file|
    file.puts "require 'migraine'\n\n"
    file.puts "migration = Migraine::Migration.new("
    file.puts "  from: '#{source}',"
    file.puts "  to: '#{destination}'"
    file.puts ")\n\n"
    
    dest_schema = database_schema_for(@destination)
    database_schema_for(@source).each do |table, columns|
      if dest_schema.has_key? table
        file.puts "migration.map '#{table}' do"
      elsif dest_schema.has_key? prefix + table
        file.puts "migration.map '#{table}' => '#{prefix + table}'"
      else
        file.puts "migration.map '#{table}' => ''"
      end
      
      columns.each do |column|
        if !dest_schema[table].nil? && dest_schema[table].include?(column)
          file.puts "  map '#{column}'"
        elsif !dest_schema[prefix + table].nil? &&
               dest_schema[prefix + table].include?(column)
          file.puts "  map '#{column}'"
        else
          file.puts "  map '#{column}' => ''"
        end
      end

      file.puts "end\n\n"
    end

    file.puts "migration.run"
  end
end