在 Rails 模型中使用多个 PostgreSQL 模式

Posted

技术标签:

【中文标题】在 Rails 模型中使用多个 PostgreSQL 模式【英文标题】:Using multiple PostgreSQL schemas with Rails models 【发布时间】:2012-02-07 01:00:56 【问题描述】:

我的 Rails 应用程序有一个 PostgreSQL 数据库。在名为“public”的模式中,存储了主要的 Rails 模型表等。我创建了一个“discogs”模式,其中的表的名称有时与“public”模式中的名称相同——这是原因之一我正在使用模式来组织它。

如何在我的应用中从“discogs”架构设置模型?我将使用 Sunspot 让 Solr 也索引这些模型。我不确定你会怎么做。

【问题讨论】:

在通过 db:create rake 任务设置数据库时如何创建非“公共”模式?将模式添加到 template1 数据库是可能的。但是有没有办法将其作为正常 rails/rake 开发过程的一部分? @TsenYing There is pg_power gem 作为一种选择。它的home is here。不过2年没更新了。另一种选择可能是在 db 命名空间中编写 create rake 任务并在那里添加你的东西。 【参考方案1】:

database.yml 中的 PostgreSQL 适配器 schema_search_path 能解决你的问题吗?

development:
  adapter: postgresql
  encoding: utf-8
  database: solidus
  host: 127.0.0.1
  port: 5432
  username: postgres
  password: postgres
  schema_search_path: "discogs,public"

或者,您可以为每个架构指定不同的连接:

public_schema:
  adapter: postgresql
  encoding: utf-8
  database: solidus
  host: 127.0.0.1
  port: 5432
  username: postgres
  password: postgres
  schema_search_path: "public"

discogs_schema:
  adapter: postgresql
  encoding: utf-8
  database: solidus
  host: 127.0.0.1
  port: 5432
  username: postgres
  password: postgres
  schema_search_path: "discogs"

每个连接定义后,创建两个模型:

class PublicSchema < ActiveRecord::Base
  self.abstract_class = true
  establish_connection :public_schema
end

class DiscoGsSchema < ActiveRecord::Base
  self.abstract_class = true
  establish_connection :discogs_schema
end

而且,您的所有模型都继承自各自的架构:

class MyModelFromPublic < PublicSchema
  set_table_name :my_table_name
end

class MyOtherModelFromDiscoGs < DiscoGsSchema
  set_table_name :disco
end

希望对你有帮助。

【讨论】:

看起来你应该在 *Schema 类中添加 self.abstract_class= true 以避免不存在的表问题。 配置schema_search_path: 是至关重要的,如果您离开它并只使用self.table_name = 'discogs.disco',那么所有的似乎都可以工作......除了database_cleaner。它使用schema_search_path 从模式中获取表列表。我省略了这一点,并且记录在测试运行之间一直存储在省略的模式表中。【参考方案2】:

rails 4.2 的正确方法是:

class Foo < ActiveRecord::Base
  self.table_name = 'myschema.foo'
end

更多信息-http://api.rubyonrails.org/classes/ActiveRecord/ModelSchema/ClassMethods.html#method-i-table_name-3D

【讨论】:

【参考方案3】:

在迁移中:

class CreateUsers < ActiveRecord::Migration
  def up
    execute 'CREATE SCHEMA settings'
    create_table 'settings.users' do |t|
      t.string :username
      t.string :email
      t.string :password

      t.timestamps null: false
    end
  end

  def down
    drop_table 'settings.users'
    execute 'DROP SCHEMA settings'
  end

end

模型可选

class User < ActiveRecord::Base
  self.table_name 'settings.users'
end

【讨论】:

【参考方案4】:

因为set_table_name 被移除,而被self.table_name 取代。

我认为你应该编码如下:

class Foo < ActiveRecord::Base
  self.table_name =  'myschema.foo'
end

【讨论】:

【参考方案5】:

做吧

class Foo < ActiveRecord::Base
  self.table_name = 'myschema.foo'
end

【讨论】:

弃用 set_table_name 支持 self.table_name= github.com/rails/rails/commit/0b72a04【参考方案6】:

方法set_table_name 已被删除。 self.table_name 工作正常。

【讨论】:

以上是关于在 Rails 模型中使用多个 PostgreSQL 模式的主要内容,如果未能解决你的问题,请参考以下文章

如何使用flex在Rails上提交多个模型?

如何将多个模式加载到 Rails 引擎或应用程序中?

Rails 跨多个模型搜索

Sunspot Solr Rails - 使用“with”搜索多个模型

Rails 4 在模型中添加新列或字段

Rails 3 从单个模型和方法创建多个记录条目