17

我正在为不同的客户端使用 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
4

4 回答 4

11

我有一个 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
    #e.g. add_column :xyz, ...
  end
end

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

Account.for_each do |account|
  SchemaUtils.with_schema(account.code) do
    #Put migration code here
  end
end
于 2010-07-07T12:49:41.973 回答
1

检查apartment专门为此目的而构建的 gem。这个棒极了。

于 2015-09-17T15:00:50.233 回答
0

我写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"
于 2014-01-16T17:38:10.120 回答
0

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

于 2010-06-28T05:30:50.093 回答