如何在分布式Gem中处理ActiveRecord迁移?

如何在分布式Gem中处理ActiveRecord迁移?,activerecord,gem,rails-migrations,Activerecord,Gem,Rails Migrations,我正在尝试使用没有Rails的ActiveRecord编写一个应用程序作为gem 我的问题是如何迁移一个已经由没有rake的用户部署的数据库,等等。我刚刚分发了一个schema.rb文件,并从中创建了数据库。但是现在我想允许用户更新到一个新的gem并迁移他们的数据库 我看过ActiveRecord::Migrator,但不知道如何使用它 例如,我如何告诉ActiveRecord::Migrator从当前的\u迁移开始运行所有迁移 有人对如何进行这项工作有什么建议或很好的参考吗?在今天早上参加了这

我正在尝试使用没有Rails的ActiveRecord编写一个应用程序作为gem

我的问题是如何迁移一个已经由没有rake的用户部署的数据库,等等。我刚刚分发了一个schema.rb文件,并从中创建了数据库。但是现在我想允许用户更新到一个新的gem并迁移他们的数据库

我看过ActiveRecord::Migrator,但不知道如何使用它

例如,我如何告诉ActiveRecord::Migrator从当前的\u迁移开始运行所有迁移


有人对如何进行这项工作有什么建议或很好的参考吗?

在今天早上参加了这个新鲜的活动后,我想到了以下几点,效果很好:

module Byr
  module Db

    class << self
      attr_accessor :config
      attr_accessor :adapter
      attr_accessor :db_name
    end

    def self.create_sqlite(config)
      require 'sqlite3'
      config = config.merge('database' => File.join(Byr.db_dir, config['database']))
      ActiveRecord::Base.establish_connection(config)
    end

    def self.create_pg(config)
      require 'pg'
      # Connect to the postgres db to create the db
      ActiveRecord::Base.establish_connection(config.merge('database' => 'postgres',
                                                           'schema_search_path' => 'public'))
      begin
        result = ActiveRecord::Base.connection.create_database(config['database'])
      rescue PG::Error, ActiveRecord::StatementInvalid => e
        unless e.message =~ /already exists/
          raise
        end
      end
      true
    end

    def self.mysql_creation_options(config)
      @charset   = ENV['CHARSET']   || 'utf8'
      @collation = ENV['COLLATION'] || 'utf8_unicode_ci'
      {:charset => (config['charset'] || @charset), :collation => (config['collation'] || @collation)}
    end

    def self.create_mysql(config)
      require 'mysql2'
      error_class = config['adapter'] =~ /mysql2/ ? Mysql2::Error : Mysql::Error
      begin
        ActiveRecord::Base.establish_connection(config.merge('database' => nil))
        ActiveRecord::Base.connection.create_database(config['database'], mysql_creation_options(config))
        ActiveRecord::Base.establish_connection(config)
      rescue error_class => sqlerr
        access_denied_error = 1045
        if sqlerr.errno == access_denied_error
          print "#{sqlerr.error}. \nPlease provide the root password for your mysql installation\n>"
          root_password = $stdin.gets.strip
          grant_statement = "GRANT ALL PRIVILEGES ON #{config['database']}.* " \
          "TO '#{config['username']}'@'localhost' " \
          "IDENTIFIED BY '#{config['password']}' WITH GRANT OPTION;"
          ActiveRecord::Base.establish_connection(config.merge(
                                                               'database' => nil, 'username' => 'root', 'password' => root_password))
          ActiveRecord::Base.connection.create_database(config['database'], mysql_creation_options(config))
          ActiveRecord::Base.connection.execute grant_statement
          ActiveRecord::Base.establish_connection(config)
        else
          Byr.warn sqlerr.error
          Byr.warn "Couldn't create database for #{config.inspect}, charset: #{config['charset'] || @charset}, collation: #{config['collation'] || @collation}"
          Byr.warn "(if you set the charset manually, make sure you have a matching collation)" if config['charset']
        end
      rescue ActiveRecord::StatementInvalid => e
        ActiveRecord::Base.establish_connection(config)
      end
    end

    def self.migrate
      sys_migration_dir = File.join(Byr.install_dir, "db/migrate")
      ActiveRecord::Migration.verbose = true
      ActiveRecord::Migrator.migrate(sys_migration_dir)
    end

    def self.connected?
      ActiveRecord::Base.connected? and
        ActiveRecord::Base.connection_config[:adapter] == adapter
    end

    def self.disconnect
      ActiveRecord::Base.connection_pool.disconnect!
    end

    # Really only for testing
    def self.drop_db
      ActiveRecord::Base.connection.drop_database(Byr.db_config)
    end
  end
end
模块Byr
模块数据库
类文件.join(Byr.db_dir,config['database']))
ActiveRecord::Base.build\u连接(配置)
结束
定义自我创建页面(配置)
需要“pg”
#连接到postgres数据库以创建数据库
ActiveRecord::Base.build_连接(config.merge('database'=>'postgres',
“架构搜索路径”=>“公共”)
开始
result=ActiveRecord::Base.connection.create_数据库(配置['database'])
rescue PG::错误,ActiveRecord::语句无效=>e
除非e.message=~/已经存在/
提升
结束
结束
真的
结束
def self.mysql_创建_选项(配置)
@charset=ENV['charset']| |'utf8'
@collation=ENV['collation']| |'utf8\U unicode\U ci'
{:charset=>(config['charset']||@charset),:collation=>(config['collation']||@collation)}
结束
def self.create_mysql(配置)
需要“mysql2”
错误\u class=config['adapter']=~/mysql2/?Mysql2::Error:Mysql::Error
开始
ActiveRecord::Base.building_连接(config.merge('database'=>nil))
ActiveRecord::Base.connection.create_数据库(配置['database'],mysql_创建选项(配置))
ActiveRecord::Base.build\u连接(配置)
救援错误\u类=>sqlerr
访问被拒绝\u错误=1045
如果sqlerr.errno==访问被拒绝\u错误
打印“#{sqlerr.error}。\n请为mysql安装提供根密码\n>”
root_password=$stdin.gets.strip
grant_statement=“授予#{config['database']}.*上的所有权限”\
“到“#{config['username']}@'localhost'”\
“由带有授权选项的“#{config['password']}”标识;”
ActiveRecord::Base.build\u连接(config.merge(
'数据库'=>nil',用户名'=>root',密码'=>root\u密码))
ActiveRecord::Base.connection.create_数据库(配置['database'],mysql_创建选项(配置))
ActiveRecord::Base.connection.execute grant\u语句
ActiveRecord::Base.build\u连接(配置)
其他的
Byr.warn sqlerr.error
Byr.warn“无法为#{config.inspect}创建数据库,字符集:#{config['charset'].@charset},排序规则:#{config['collation'].@collation}”
Byr.warn“(如果手动设置字符集,请确保具有匹配的排序规则)”if config['charset']
结束
rescue ActiveRecord::语句无效=>e
ActiveRecord::Base.build\u连接(配置)
结束
结束
def自我迁移
sys\u migration\u dir=File.join(Byr.install\u dir,“db/migrate”)
ActiveRecord::Migration.verbose=true
ActiveRecord::Migrator.migrate(sys\u migration\u dir)
结束
def自动连接?
ActiveRecord::Base.connected?和
ActiveRecord::Base.connection\u config[:适配器]==适配器
结束
def自动断开
ActiveRecord::Base.connection\u pool.disconnect!
结束
#真的只是为了测试
def self.drop_db
ActiveRecord::Base.connection.drop_数据库(Byr.db_config)
结束
结束
结束
然后,要通过迁移初始化数据库:

module Byr
  class << self
    attr_accessor :install_dir
    attr_accessor :db_dir
    attr_accessor :config_dir
    attr_accessor :config_file
    attr_accessor :config
    attr_accessor :db_config
    attr_accessor :adapter
    attr_accessor :database
  def self.create_db
    case db_config['adapter']
    when /postgresql/
      Byr::Db.create_pg(db_config)
    when /sqlite/
      Byr::Db.create_sqlite(db_config)
    when /mysql/
      Byr::Db.create_mysql(db_config)
    else
      raise ByrError "Your config.yml file specifies an unknown database adapter \'#{config['adapter']}\'"
    end
  end

  def self.connect_db(reconnect = false)
    unless reconnect
      return true if Byr.connected?
    end
    ActiveRecord::Base.establish_connection(db_config)
  end

  def self.migrate
    Byr::Db.migrate
  end

  def self.init(connect = true, adapter = nil)
    adapter = canonicalize_adapter(adapter) if adapter
    setup_db_config
    if connect
      create_db and connect_db and migrate
    end
  end
end
模块Byr
班