mysql-inspector 0.0.6 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +5 -3
- data/CHANGELOG.md +8 -0
- data/Gemfile +6 -0
- data/LICENSE +20 -0
- data/README.md +82 -0
- data/Rakefile +36 -14
- data/bin/mysql-inspector +9 -85
- data/lib/mysql-inspector.rb +1 -226
- data/lib/mysql_inspector.rb +30 -0
- data/lib/mysql_inspector/access.rb +64 -0
- data/lib/mysql_inspector/ar/access.rb +55 -0
- data/lib/mysql_inspector/cli.rb +291 -0
- data/lib/mysql_inspector/column.rb +21 -0
- data/lib/mysql_inspector/config.rb +82 -0
- data/lib/mysql_inspector/constraint.rb +28 -0
- data/lib/mysql_inspector/diff.rb +82 -0
- data/lib/mysql_inspector/dump.rb +70 -0
- data/lib/mysql_inspector/grep.rb +65 -0
- data/lib/mysql_inspector/index.rb +25 -0
- data/lib/mysql_inspector/migrations.rb +37 -0
- data/lib/mysql_inspector/railtie.rb +17 -0
- data/lib/mysql_inspector/railties/databases.rake +92 -0
- data/lib/mysql_inspector/table.rb +147 -0
- data/lib/mysql_inspector/table_part.rb +21 -0
- data/lib/mysql_inspector/version.rb +3 -0
- data/mysql-inspector.gemspec +17 -36
- data/test/fixtures/migrate/111_create_users.rb +7 -0
- data/test/fixtures/migrate/222_create_things.rb +9 -0
- data/test/helper.rb +125 -0
- data/test/helper_ar.rb +37 -0
- data/test/helpers/mysql_schemas.rb +82 -0
- data/test/helpers/mysql_utils.rb +35 -0
- data/test/helpers/string_unindented.rb +13 -0
- data/test/mysql_inspector/cli_basics_test.rb +77 -0
- data/test/mysql_inspector/cli_diff_test.rb +60 -0
- data/test/mysql_inspector/cli_grep_test.rb +74 -0
- data/test/mysql_inspector/cli_load_test.rb +43 -0
- data/test/mysql_inspector/cli_write_test.rb +58 -0
- data/test/mysql_inspector/config_test.rb +14 -0
- data/test/mysql_inspector/diff_test.rb +82 -0
- data/test/mysql_inspector/dump_test.rb +81 -0
- data/test/mysql_inspector/grep_test.rb +61 -0
- data/test/mysql_inspector/table_test.rb +123 -0
- data/test/mysql_inspector_ar/ar_dump_test.rb +29 -0
- data/test/mysql_inspector_ar/ar_migrations_test.rb +47 -0
- metadata +123 -49
- data/README +0 -48
- data/VERSION +0 -1
| @@ -0,0 +1,147 @@ | |
| 1 | 
            +
            module MysqlInspector
         | 
| 2 | 
            +
              class Table
         | 
| 3 | 
            +
             | 
| 4 | 
            +
                BACKTICK_WORD = /`([^`]+)`/
         | 
| 5 | 
            +
                BACKTICK_CSV = /\(([^\)]+)\)/
         | 
| 6 | 
            +
                REFERENCE_OPTION = /RESTRICT|CASCADE|SET NULL|NO ACTION/
         | 
| 7 | 
            +
             | 
| 8 | 
            +
                def initialize(schema)
         | 
| 9 | 
            +
                  @schema = schema
         | 
| 10 | 
            +
                  @lines = schema.split("\n")
         | 
| 11 | 
            +
                  @lines.delete_if { |line| line =~ /(\/\*|--)/ or line.strip.empty? }
         | 
| 12 | 
            +
                end
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                # Public: Get then name of the table.
         | 
| 15 | 
            +
                #
         | 
| 16 | 
            +
                # Returns a String.
         | 
| 17 | 
            +
                def table_name
         | 
| 18 | 
            +
                  @table_name ||= begin
         | 
| 19 | 
            +
                    line = @lines.find { |line| line =~ /CREATE TABLE #{BACKTICK_WORD}/}
         | 
| 20 | 
            +
                    $1 if line
         | 
| 21 | 
            +
                  end
         | 
| 22 | 
            +
                end
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                # Public: Get all of the columns defined in the table.
         | 
| 25 | 
            +
                #
         | 
| 26 | 
            +
                # Returns an Array of MysqlInspector::Column.
         | 
| 27 | 
            +
                def columns
         | 
| 28 | 
            +
                  @columns ||= @lines.map { |line|
         | 
| 29 | 
            +
                    if line.strip =~ /^#{BACKTICK_WORD} ([\w\(\)\d]+)/
         | 
| 30 | 
            +
                      name = $1
         | 
| 31 | 
            +
                      sql_type = $2
         | 
| 32 | 
            +
                      nullable = !!(line !~ /NOT NULL/)
         | 
| 33 | 
            +
                      default = line[/DEFAULT ('?[^']+'?)/, 1]
         | 
| 34 | 
            +
                      default = nil if default =~ /NULL/
         | 
| 35 | 
            +
                      auto_increment = !!(line =~ /AUTO_INCREMENT/)
         | 
| 36 | 
            +
                      table_part line, MysqlInspector::Column.new(name, sql_type, nullable, default, auto_increment)
         | 
| 37 | 
            +
                    end
         | 
| 38 | 
            +
                  }.compact.sort
         | 
| 39 | 
            +
                end
         | 
| 40 | 
            +
             | 
| 41 | 
            +
                # Public: Get all of the indices defined in the table
         | 
| 42 | 
            +
                #
         | 
| 43 | 
            +
                # Returns an Array of MysqlInspector::Index.
         | 
| 44 | 
            +
                def indices
         | 
| 45 | 
            +
                  @indices ||= @lines.map { |line|
         | 
| 46 | 
            +
                    if line.strip =~ /^(UNIQUE )?KEY #{BACKTICK_WORD} #{BACKTICK_CSV}/
         | 
| 47 | 
            +
                      unique = !!$1
         | 
| 48 | 
            +
                      name = $2
         | 
| 49 | 
            +
                      column_names = backtick_names_in_csv($3)
         | 
| 50 | 
            +
                      table_part line, MysqlInspector::Index.new(name, column_names, unique)
         | 
| 51 | 
            +
                    elsif line.strip =~ /^PRIMARY KEY #{BACKTICK_CSV}/
         | 
| 52 | 
            +
                      unique = true
         | 
| 53 | 
            +
                      name = "PRIMARY KEY"
         | 
| 54 | 
            +
                      column_names = backtick_names_in_csv($1)
         | 
| 55 | 
            +
                      table_part line, MysqlInspector::Index.new(name, column_names, unique)
         | 
| 56 | 
            +
                    end
         | 
| 57 | 
            +
                  }.compact.sort
         | 
| 58 | 
            +
                end
         | 
| 59 | 
            +
             | 
| 60 | 
            +
                # Public: Get all of the constraints defined in the table
         | 
| 61 | 
            +
                #
         | 
| 62 | 
            +
                # Returns an Array of MysqlInspector::Constraint.
         | 
| 63 | 
            +
                def constraints
         | 
| 64 | 
            +
                  @constraints ||= @lines.map { |line|
         | 
| 65 | 
            +
                    if line.strip =~ /^CONSTRAINT #{BACKTICK_WORD} FOREIGN KEY #{BACKTICK_CSV} REFERENCES #{BACKTICK_WORD} #{BACKTICK_CSV} ON DELETE (#{REFERENCE_OPTION}) ON UPDATE (#{REFERENCE_OPTION})$/
         | 
| 66 | 
            +
                      name = $1
         | 
| 67 | 
            +
                      column_names = backtick_names_in_csv($2)
         | 
| 68 | 
            +
                      foreign_name = $3
         | 
| 69 | 
            +
                      foreign_column_names = backtick_names_in_csv($4)
         | 
| 70 | 
            +
                      on_delete = $5
         | 
| 71 | 
            +
                      on_update = $6
         | 
| 72 | 
            +
                      table_part line, MysqlInspector::Constraint.new(name, column_names, foreign_name, foreign_column_names, on_update, on_delete)
         | 
| 73 | 
            +
                    end
         | 
| 74 | 
            +
                  }.compact.sort
         | 
| 75 | 
            +
                end
         | 
| 76 | 
            +
             | 
| 77 | 
            +
                def options
         | 
| 78 | 
            +
                  @options ||= begin
         | 
| 79 | 
            +
                    if line = @lines.find { |line| line =~ /ENGINE=/}
         | 
| 80 | 
            +
                      # AUTO_INCREMENT is not useful.
         | 
| 81 | 
            +
                      line.sub!(/AUTO_INCREMENT=\d+/, '')
         | 
| 82 | 
            +
                      # Compact multiple spaces.
         | 
| 83 | 
            +
                      line.gsub!(/\s+/, ' ')
         | 
| 84 | 
            +
                      # Remove paren at the beginning.
         | 
| 85 | 
            +
                      line.sub!(/^\)\s*/, '')
         | 
| 86 | 
            +
                      # Remove semicolon at the end.
         | 
| 87 | 
            +
                      line.chomp!(';')
         | 
| 88 | 
            +
                      line
         | 
| 89 | 
            +
                    end
         | 
| 90 | 
            +
                  end
         | 
| 91 | 
            +
                end
         | 
| 92 | 
            +
             | 
| 93 | 
            +
                def eql?(other)
         | 
| 94 | 
            +
                  table_name == other.table_name &&
         | 
| 95 | 
            +
                      columns == other.columns &&
         | 
| 96 | 
            +
                      indices == other.indices &&
         | 
| 97 | 
            +
                      constraints == other.constraints &&
         | 
| 98 | 
            +
                      options = other.options
         | 
| 99 | 
            +
                end
         | 
| 100 | 
            +
             | 
| 101 | 
            +
                alias == eql?
         | 
| 102 | 
            +
             | 
| 103 | 
            +
                def <=>(other)
         | 
| 104 | 
            +
                  table_name <=> other.table_name
         | 
| 105 | 
            +
                end
         | 
| 106 | 
            +
             | 
| 107 | 
            +
                def to_simple_schema
         | 
| 108 | 
            +
                  lines = []
         | 
| 109 | 
            +
             | 
| 110 | 
            +
                  lines << "CREATE TABLE `#{table_name}`"
         | 
| 111 | 
            +
                  lines << nil
         | 
| 112 | 
            +
                  simple_schema_items(lines, columns)
         | 
| 113 | 
            +
                  simple_schema_items(lines, indices)
         | 
| 114 | 
            +
                  simple_schema_items(lines, constraints)
         | 
| 115 | 
            +
                  lines << options
         | 
| 116 | 
            +
             | 
| 117 | 
            +
                  lines.join("\n")
         | 
| 118 | 
            +
                end
         | 
| 119 | 
            +
             | 
| 120 | 
            +
                def to_sql
         | 
| 121 | 
            +
                  lines = []
         | 
| 122 | 
            +
             | 
| 123 | 
            +
                  lines << "CREATE TABLE `#{table_name}` ("
         | 
| 124 | 
            +
                  lines << (columns + indices + constraints).map { |x| "  #{x.to_sql}" }.join(",\n")
         | 
| 125 | 
            +
                  lines << ") #{options}"
         | 
| 126 | 
            +
             | 
| 127 | 
            +
                  lines.join("\n")
         | 
| 128 | 
            +
                end
         | 
| 129 | 
            +
             | 
| 130 | 
            +
              protected
         | 
| 131 | 
            +
             | 
| 132 | 
            +
                def simple_schema_items(lines, items)
         | 
| 133 | 
            +
                  lines.concat items.map { |item| item.to_sql }
         | 
| 134 | 
            +
                  lines << nil if items.any?
         | 
| 135 | 
            +
                end
         | 
| 136 | 
            +
             | 
| 137 | 
            +
                def table_part(line, part)
         | 
| 138 | 
            +
                  part.table = self
         | 
| 139 | 
            +
                  part
         | 
| 140 | 
            +
                end
         | 
| 141 | 
            +
             | 
| 142 | 
            +
                def backtick_names_in_csv(string)
         | 
| 143 | 
            +
                  string.split(',').map { |x| x[BACKTICK_WORD, 1] }
         | 
| 144 | 
            +
                end
         | 
| 145 | 
            +
             | 
| 146 | 
            +
              end
         | 
| 147 | 
            +
            end
         | 
| @@ -0,0 +1,21 @@ | |
| 1 | 
            +
            module MysqlInspector
         | 
| 2 | 
            +
              module TablePart
         | 
| 3 | 
            +
             | 
| 4 | 
            +
                attr_accessor :table
         | 
| 5 | 
            +
             | 
| 6 | 
            +
                def <=>(other)
         | 
| 7 | 
            +
                  name <=> other.name
         | 
| 8 | 
            +
                end
         | 
| 9 | 
            +
             | 
| 10 | 
            +
              protected
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                def quote(word)
         | 
| 13 | 
            +
                  "`#{word}`"
         | 
| 14 | 
            +
                end
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                def paren(words)
         | 
| 17 | 
            +
                  "(#{words * ","})"
         | 
| 18 | 
            +
                end
         | 
| 19 | 
            +
             | 
| 20 | 
            +
              end
         | 
| 21 | 
            +
            end
         | 
    
        data/mysql-inspector.gemspec
    CHANGED
    
    | @@ -1,44 +1,25 @@ | |
| 1 | 
            -
            # Generated by jeweler
         | 
| 2 | 
            -
            # DO NOT EDIT THIS FILE DIRECTLY
         | 
| 3 | 
            -
            # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
         | 
| 4 1 | 
             
            # -*- encoding: utf-8 -*-
         | 
| 2 | 
            +
            $:.push File.expand_path("../lib", __FILE__)
         | 
| 3 | 
            +
            require "mysql_inspector/version"
         | 
| 5 4 |  | 
| 6 5 | 
             
            Gem::Specification.new do |s|
         | 
| 7 | 
            -
              s.name | 
| 8 | 
            -
              s.version | 
| 6 | 
            +
              s.name        = "mysql-inspector"
         | 
| 7 | 
            +
              s.version     = MysqlInspector::VERSION
         | 
| 8 | 
            +
              s.authors     = ["Ryan Carver"]
         | 
| 9 | 
            +
              s.email       = ["ryan@ryancarver.com"]
         | 
| 10 | 
            +
              s.homepage    = ""
         | 
| 11 | 
            +
              s.summary     = %q{Store and understand your MySQL schema}
         | 
| 12 | 
            +
              s.description = %q{Store and understand your MySQL schema}
         | 
| 9 13 |  | 
| 10 | 
            -
              s. | 
| 11 | 
            -
             | 
| 12 | 
            -
              s. | 
| 13 | 
            -
              s. | 
| 14 | 
            -
              s. | 
| 15 | 
            -
              s.executables = ["mysql-inspector"]
         | 
| 16 | 
            -
              s.extra_rdoc_files = [
         | 
| 17 | 
            -
                "README"
         | 
| 18 | 
            -
              ]
         | 
| 19 | 
            -
              s.files = [
         | 
| 20 | 
            -
                ".gitignore",
         | 
| 21 | 
            -
                 "README",
         | 
| 22 | 
            -
                 "Rakefile",
         | 
| 23 | 
            -
                 "VERSION",
         | 
| 24 | 
            -
                 "bin/mysql-inspector",
         | 
| 25 | 
            -
                 "lib/mysql-inspector.rb",
         | 
| 26 | 
            -
                 "mysql-inspector.gemspec"
         | 
| 27 | 
            -
              ]
         | 
| 28 | 
            -
              s.homepage = %q{http://github.com/rcarver/mysql-inspector}
         | 
| 29 | 
            -
              s.rdoc_options = ["--charset=UTF-8"]
         | 
| 14 | 
            +
              s.rubyforge_project = "mysql-inspector"
         | 
| 15 | 
            +
             | 
| 16 | 
            +
              s.files         = `git ls-files`.split("\n")
         | 
| 17 | 
            +
              s.test_files    = `git ls-files -- {test,spec,features}/*`.split("\n")
         | 
| 18 | 
            +
              s.executables   = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
         | 
| 30 19 | 
             
              s.require_paths = ["lib"]
         | 
| 31 | 
            -
              s.rubygems_version = %q{1.3.6}
         | 
| 32 | 
            -
              s.summary = %q{Tools for identifying changes to a MySQL schema}
         | 
| 33 20 |  | 
| 34 | 
            -
               | 
| 35 | 
            -
             | 
| 36 | 
            -
                s.specification_version = 3
         | 
| 21 | 
            +
              s.add_development_dependency "rake"
         | 
| 22 | 
            +
              s.add_development_dependency "minitest"
         | 
| 37 23 |  | 
| 38 | 
            -
             | 
| 39 | 
            -
                else
         | 
| 40 | 
            -
                end
         | 
| 41 | 
            -
              else
         | 
| 42 | 
            -
              end
         | 
| 24 | 
            +
              # s.add_runtime_dependency "rest-client"
         | 
| 43 25 | 
             
            end
         | 
| 44 | 
            -
             | 
    
        data/test/helper.rb
    ADDED
    
    | @@ -0,0 +1,125 @@ | |
| 1 | 
            +
            require 'minitest/autorun'
         | 
| 2 | 
            +
            require 'minitest/mock'
         | 
| 3 | 
            +
            require 'open3'
         | 
| 4 | 
            +
            require 'ostruct'
         | 
| 5 | 
            +
            require 'stringio'
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            require 'mysql_inspector'
         | 
| 8 | 
            +
             | 
| 9 | 
            +
            require 'helpers/mysql_utils'
         | 
| 10 | 
            +
            require 'helpers/mysql_schemas'
         | 
| 11 | 
            +
            require 'helpers/string_unindented'
         | 
| 12 | 
            +
             | 
| 13 | 
            +
            class MysqlInspectorSpec < MiniTest::Spec
         | 
| 14 | 
            +
              include MysqlSchemas
         | 
| 15 | 
            +
             | 
| 16 | 
            +
              def it msg
         | 
| 17 | 
            +
                raise "A block must not be passed to the example-level +it+" if block_given?
         | 
| 18 | 
            +
                @__current_msg = "it #{msg}"
         | 
| 19 | 
            +
              end
         | 
| 20 | 
            +
             | 
| 21 | 
            +
              def message msg = nil, ending = ".", &default
         | 
| 22 | 
            +
                super(msg || @__current_msg, ending, &default)
         | 
| 23 | 
            +
              end
         | 
| 24 | 
            +
             | 
| 25 | 
            +
              register_spec_type(self) { |desc| true }
         | 
| 26 | 
            +
             | 
| 27 | 
            +
              # Create a temporary directory. This directory will exist for the life of
         | 
| 28 | 
            +
              # the spec.
         | 
| 29 | 
            +
              #
         | 
| 30 | 
            +
              # id - Identifier of the tmpdir (default: the default identifier).
         | 
| 31 | 
            +
              #
         | 
| 32 | 
            +
              # Returns a String.
         | 
| 33 | 
            +
              def tmpdir(id=:default)
         | 
| 34 | 
            +
                @tmpdirs[id] ||= Dir.mktmpdir
         | 
| 35 | 
            +
              end
         | 
| 36 | 
            +
             | 
| 37 | 
            +
              # Get the name of the test database.
         | 
| 38 | 
            +
              #
         | 
| 39 | 
            +
              # Returns a String.
         | 
| 40 | 
            +
              def database_name
         | 
| 41 | 
            +
                "mysql_inspector_test"
         | 
| 42 | 
            +
              end
         | 
| 43 | 
            +
             | 
| 44 | 
            +
              # Create a test mysql database. The database will exist for the life
         | 
| 45 | 
            +
              # of the spec.
         | 
| 46 | 
            +
              #
         | 
| 47 | 
            +
              # schema - String schema to create (default: no schema).
         | 
| 48 | 
            +
              #
         | 
| 49 | 
            +
              # Returns nothing.
         | 
| 50 | 
            +
              def create_mysql_database(schema="")
         | 
| 51 | 
            +
                @mysql_database = true
         | 
| 52 | 
            +
                MysqlUtils.create_mysql_database(database_name, schema)
         | 
| 53 | 
            +
              end
         | 
| 54 | 
            +
             | 
| 55 | 
            +
              # Drop the test mysql database.
         | 
| 56 | 
            +
              #
         | 
| 57 | 
            +
              # Returns nothing.
         | 
| 58 | 
            +
              def drop_mysql_database
         | 
| 59 | 
            +
                MysqlUtils.drop_mysql_database(database_name)
         | 
| 60 | 
            +
              end
         | 
| 61 | 
            +
             | 
| 62 | 
            +
              # Get access to the mysql database.
         | 
| 63 | 
            +
              #
         | 
| 64 | 
            +
              # Returns a MysqlInspector:Access.
         | 
| 65 | 
            +
              def access
         | 
| 66 | 
            +
                (@access ||= {})[database_name] ||= MysqlInspector::Access.new(database_name, "root", nil, "mysql")
         | 
| 67 | 
            +
              end
         | 
| 68 | 
            +
             | 
| 69 | 
            +
              let(:config) { MysqlInspector::Config.new }
         | 
| 70 | 
            +
             | 
| 71 | 
            +
              before do
         | 
| 72 | 
            +
                @tmpdirs = {}
         | 
| 73 | 
            +
                @mysql_database = nil
         | 
| 74 | 
            +
              end
         | 
| 75 | 
            +
             | 
| 76 | 
            +
              after do
         | 
| 77 | 
            +
                @tmpdirs.values.each { |dir| FileUtils.rm_rf dir }
         | 
| 78 | 
            +
                drop_mysql_database if @mysql_database
         | 
| 79 | 
            +
              end
         | 
| 80 | 
            +
            end
         | 
| 81 | 
            +
             | 
| 82 | 
            +
            class MysqlInspectorCliSpec < MysqlInspectorSpec
         | 
| 83 | 
            +
             | 
| 84 | 
            +
              register_spec_type(self) { |desc| desc =~ /mysql-inspector/ }
         | 
| 85 | 
            +
             | 
| 86 | 
            +
              before do
         | 
| 87 | 
            +
                config.dir = tmpdir
         | 
| 88 | 
            +
              end
         | 
| 89 | 
            +
             | 
| 90 | 
            +
              def parse_command(klass, argv)
         | 
| 91 | 
            +
                command = klass.new(config, StringIO.new, StringIO.new)
         | 
| 92 | 
            +
                command.parse!(argv)
         | 
| 93 | 
            +
                command
         | 
| 94 | 
            +
              end
         | 
| 95 | 
            +
             | 
| 96 | 
            +
              def run_command(klass, argv)
         | 
| 97 | 
            +
                command = klass.new(config, StringIO.new, StringIO.new)
         | 
| 98 | 
            +
                command.parse!(argv)
         | 
| 99 | 
            +
                command.run!
         | 
| 100 | 
            +
                command
         | 
| 101 | 
            +
              end
         | 
| 102 | 
            +
             | 
| 103 | 
            +
              def mysql_inspector(args)
         | 
| 104 | 
            +
                cli = MysqlInspector::CLI.new(config, StringIO.new, StringIO.new)
         | 
| 105 | 
            +
                argv = args.split(/\s+/).map { |x| x.gsub(/'/, '') }
         | 
| 106 | 
            +
                cli.run!(argv)
         | 
| 107 | 
            +
                cli
         | 
| 108 | 
            +
              end
         | 
| 109 | 
            +
             | 
| 110 | 
            +
              def inspect_database(args)
         | 
| 111 | 
            +
                mysql_inspector args
         | 
| 112 | 
            +
              end
         | 
| 113 | 
            +
             | 
| 114 | 
            +
              def stdout
         | 
| 115 | 
            +
                subject.stdout.string.chomp
         | 
| 116 | 
            +
              end
         | 
| 117 | 
            +
             | 
| 118 | 
            +
              def stderr
         | 
| 119 | 
            +
                subject.stderr.string.chomp
         | 
| 120 | 
            +
              end
         | 
| 121 | 
            +
             | 
| 122 | 
            +
              def status
         | 
| 123 | 
            +
                subject.status
         | 
| 124 | 
            +
              end
         | 
| 125 | 
            +
            end
         | 
    
        data/test/helper_ar.rb
    ADDED
    
    | @@ -0,0 +1,37 @@ | |
| 1 | 
            +
            require 'active_record'
         | 
| 2 | 
            +
            require 'mysql2'
         | 
| 3 | 
            +
            require 'helper'
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            class MysqlInspectorActiveRecordSpec < MysqlInspectorSpec
         | 
| 6 | 
            +
             | 
| 7 | 
            +
              register_spec_type(self) { |desc| desc =~ /activerecord/ }
         | 
| 8 | 
            +
             | 
| 9 | 
            +
              before do
         | 
| 10 | 
            +
                unless ActiveRecord::Base.connected?
         | 
| 11 | 
            +
                  ActiveRecord::Base.establish_connection(
         | 
| 12 | 
            +
                    :adapter => :mysql2,
         | 
| 13 | 
            +
                    :database => database_name,
         | 
| 14 | 
            +
                    :username => "root",
         | 
| 15 | 
            +
                    :password => nil
         | 
| 16 | 
            +
                  )
         | 
| 17 | 
            +
                end
         | 
| 18 | 
            +
                create_mysql_database
         | 
| 19 | 
            +
                config.migrations = true
         | 
| 20 | 
            +
              end
         | 
| 21 | 
            +
             | 
| 22 | 
            +
              # Execute all of the fixture migrations.
         | 
| 23 | 
            +
              #
         | 
| 24 | 
            +
              # Returns nothing.
         | 
| 25 | 
            +
              def run_active_record_migrations!
         | 
| 26 | 
            +
                ActiveRecord::Migration.verbose = false
         | 
| 27 | 
            +
                ActiveRecord::Migrator.migrate(["test/fixtures/migrate"])
         | 
| 28 | 
            +
              end
         | 
| 29 | 
            +
             | 
| 30 | 
            +
              # Get access to the mysql database.
         | 
| 31 | 
            +
              #
         | 
| 32 | 
            +
              # Returns a MysqlInspector:AR::Access.
         | 
| 33 | 
            +
              def access
         | 
| 34 | 
            +
                MysqlInspector::AR::Access.new(ActiveRecord::Base.connection)
         | 
| 35 | 
            +
              end
         | 
| 36 | 
            +
             | 
| 37 | 
            +
            end
         | 
| @@ -0,0 +1,82 @@ | |
| 1 | 
            +
            require 'helpers/string_unindented'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            # Sample table schemas used for testing.
         | 
| 4 | 
            +
            module MysqlSchemas
         | 
| 5 | 
            +
             | 
| 6 | 
            +
              # A sample starting database.
         | 
| 7 | 
            +
              def schema_a
         | 
| 8 | 
            +
                [ideas_schema, colors_schema, things_schema_1].join(";\n")
         | 
| 9 | 
            +
              end
         | 
| 10 | 
            +
             | 
| 11 | 
            +
              # A sample changed database.
         | 
| 12 | 
            +
              def schema_b
         | 
| 13 | 
            +
                [users_schema, ideas_schema, things_schema_2].join(";\n")
         | 
| 14 | 
            +
              end
         | 
| 15 | 
            +
             | 
| 16 | 
            +
              def colors_schema
         | 
| 17 | 
            +
                <<-STR.unindented
         | 
| 18 | 
            +
                  CREATE TABLE `colors` (
         | 
| 19 | 
            +
                    `name` varchar(255) NOT NULL,
         | 
| 20 | 
            +
                    UNIQUE KEY `colors_primary` (`name`)
         | 
| 21 | 
            +
                  ) ENGINE=InnoDB DEFAULT CHARSET=utf8
         | 
| 22 | 
            +
                STR
         | 
| 23 | 
            +
              end
         | 
| 24 | 
            +
             | 
| 25 | 
            +
              def ideas_schema
         | 
| 26 | 
            +
                <<-STR.unindented
         | 
| 27 | 
            +
                  CREATE TABLE `ideas` (
         | 
| 28 | 
            +
                    `id` int(11) NOT NULL AUTO_INCREMENT,
         | 
| 29 | 
            +
                    `name` varchar(255) NOT NULL,
         | 
| 30 | 
            +
                    `description` text NOT NULL,
         | 
| 31 | 
            +
                    PRIMARY KEY (`id`),
         | 
| 32 | 
            +
                    KEY `name` (`name`)
         | 
| 33 | 
            +
                  ) ENGINE=InnoDB DEFAULT CHARSET=utf8
         | 
| 34 | 
            +
                STR
         | 
| 35 | 
            +
              end
         | 
| 36 | 
            +
             | 
| 37 | 
            +
              def users_schema
         | 
| 38 | 
            +
                <<-STR.unindented
         | 
| 39 | 
            +
                  CREATE TABLE `users` (
         | 
| 40 | 
            +
                    `id` int(11) NOT NULL AUTO_INCREMENT,
         | 
| 41 | 
            +
                    `first_name` varchar(255) NOT NULL,
         | 
| 42 | 
            +
                    `last_name` varchar(255) NOT NULL,
         | 
| 43 | 
            +
                    UNIQUE KEY `users_primary` (`id`),
         | 
| 44 | 
            +
                    KEY `name` (`first_name`,`last_name`)
         | 
| 45 | 
            +
                  ) ENGINE=InnoDB DEFAULT CHARSET=utf8
         | 
| 46 | 
            +
                STR
         | 
| 47 | 
            +
              end
         | 
| 48 | 
            +
             | 
| 49 | 
            +
              def things_schema_1
         | 
| 50 | 
            +
                <<-STR.unindented
         | 
| 51 | 
            +
                  CREATE TABLE `things` (
         | 
| 52 | 
            +
                    `id` int(11) NOT NULL AUTO_INCREMENT,
         | 
| 53 | 
            +
                    `name` varchar(255) NOT NULL DEFAULT 'toy',
         | 
| 54 | 
            +
                    `weight` int(11) DEFAULT NULL,
         | 
| 55 | 
            +
                    `color` varchar(255) NOT NULL,
         | 
| 56 | 
            +
                    UNIQUE KEY `things_primary` (`id`),
         | 
| 57 | 
            +
                    KEY `color` (`color`),
         | 
| 58 | 
            +
                    CONSTRAINT `belongs_to_color` FOREIGN KEY (`color`) REFERENCES `colors` (`name`) ON DELETE NO ACTION ON UPDATE CASCADE
         | 
| 59 | 
            +
                  ) ENGINE=InnoDB DEFAULT CHARSET=utf8
         | 
| 60 | 
            +
                STR
         | 
| 61 | 
            +
              end
         | 
| 62 | 
            +
             | 
| 63 | 
            +
              def things_schema_2
         | 
| 64 | 
            +
                <<-STR.unindented
         | 
| 65 | 
            +
                  CREATE TABLE `things` (
         | 
| 66 | 
            +
                    `id` int(11) NOT NULL AUTO_INCREMENT,
         | 
| 67 | 
            +
                    `name` varchar(255) NOT NULL DEFAULT 'toy',
         | 
| 68 | 
            +
                    `weight` int(11) DEFAULT NULL,
         | 
| 69 | 
            +
                    `first_name` varchar(255) NOT NULL,
         | 
| 70 | 
            +
                    `last_name` varchar(255) NOT NULL,
         | 
| 71 | 
            +
                    UNIQUE KEY `things_primary` (`id`),
         | 
| 72 | 
            +
                    KEY `name` (`first_name`,`last_name`),
         | 
| 73 | 
            +
                    CONSTRAINT `belongs_to_user` FOREIGN KEY (`first_name`, `last_name`) REFERENCES `users` (`first_name`, `last_name`) ON DELETE NO ACTION ON UPDATE CASCADE
         | 
| 74 | 
            +
                  ) ENGINE=InnoDB DEFAULT CHARSET=utf8
         | 
| 75 | 
            +
                STR
         | 
| 76 | 
            +
              end
         | 
| 77 | 
            +
             | 
| 78 | 
            +
              def things_schema
         | 
| 79 | 
            +
                things_schema_2
         | 
| 80 | 
            +
              end
         | 
| 81 | 
            +
            end
         | 
| 82 | 
            +
             |