如何在分布式Gem中处理ActiveRecord迁移?
我正在尝试使用没有Rails的ActiveRecord编写一个应用程序作为gem 我的问题是如何迁移一个已经由没有rake的用户部署的数据库,等等。我刚刚分发了一个schema.rb文件,并从中创建了数据库。但是现在我想允许用户更新到一个新的gem并迁移他们的数据库 我看过ActiveRecord::Migrator,但不知道如何使用它 例如,我如何告诉ActiveRecord::Migrator从当前的\u迁移开始运行所有迁移如何在分布式Gem中处理ActiveRecord迁移?,activerecord,gem,rails-migrations,Activerecord,Gem,Rails Migrations,我正在尝试使用没有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
班