Rails 迁移(PostgreSQL模式)

17

我正在开发一个多租户的Rails应用程序,使用PostgreSQL的不同模式为不同的客户提供服务。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

据我所知,Liquibase 可以处理数据库模式。 - Janning Vygen
1
@Janning Liquibase不是与Rails使用的ActiveRecord模型兼容的解决方案。 - lillq
4个回答

12

我有一个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

1

检查一下专门为此目的构建的 apartment gem。它非常棒。


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"

0

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


2
PostgreSQL中的模式位于数据库内。例如,一个数据库可以有多个模式。 - lillq

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接