PostgreSQL模式的Rails迁移

我正在为不同的客户端使用PostgreSQL模式开发多租户rails应用程序。 Rails迁移不适用于开箱即用的多个模式,所以我做了以下rake任务来迁移所有模式,它似乎工作。 我的问题是,如果其他人实施了更好,更优雅的解决方案。 我也非常满意一个很好的教程,包括使用多个模式的PostgreSQL的rails代码示例。 到目前为止,我只找到了关于这个主题的一个很好的演讲http://aac2009.confreaks.com/06-feb-2009-14-30-writing-multi-tenant-applications-in-rails-guy-naor.html和我的目标是tomayko.com/writings/rails-multiple-connections

desc 'Migrates all postgres schemas' task :schemas do # get all schemas env = "#{RAILS_ENV}" config = YAML::load(File.open('config/database.yml')) ActiveRecord::Base.establish_connection(config[env]) schemas = ActiveRecord::Base.connection.select_values("select * from pg_namespace where nspname != 'information_schema' AND nspname NOT LIKE 'pg%'") puts "Migrate schemas: #{schemas.inspect}" # migrate each schema schemas.each do |schema| puts "Migrate schema: #{schema}" config = YAML::load(File.open('config/database.yml')) config[env]["schema_search_path"] = schema ActiveRecord::Base.establish_connection(config[env]) ActiveRecord::Base.logger = Logger.new(STDOUT) ActiveRecord::Migrator.migrate('db/migrate', ENV["VERSION"] ? ENV["VERSION"].to_i : nil) end end 

我有一个schema_utils库,我使用它并具有以下方法来处理迁移:

  def self.with_schema(schema_name, &block) conn = ActiveRecord::Base.connection old_schema_search_path = conn.schema_search_path conn.schema_search_path = schema_name begin yield ensure conn.schema_search_path = old_schema_search_path end end 

然后我正常使用迁移,因此我可以继续调用rake:migrate现在,您可以在迁移中使用:

 ... schemas.each do |schema| SchemaUtils.with_schema(schema) do #Put migration code here #eg add_column :xyz, ... end end 

因为我倾向于将模式映射到帐户代码,所以我执行以下操作:

 Account.for_each do |account| SchemaUtils.with_schema(account.code) do #Put migration code here end end 

我不确定我的问题是否正确,但是你不需要在database.yml声明更多的环境,每个环境中指定了不同的“数据库”吗?

我写了pg_migrate是因为这些场景,即多个应用程序共享同一个数据库的情况。 可能有一种Rails方式来处理这个问题(引擎?)但是我经常有另一个应用程序不是Rails,它也需要数据库……那么什么呢?

在这种情况下,pg_migrate的关键特性是它可以生成ruby gem; 因此,可以与所有下游应用程序分开维护数据库架构,但所有人都可以引用它。

在你的Rails Gemfile中,在使用pg_migrate的’package’命令构建ruby gem之后,你可以:

 gem 'my_db', gem 'jam_db', :path=> "../my_db/gem_package" 

检查为此目的而建造的apartmentgem。 这个棒极了。