Rails中的多个数据库
可以这样做吗? 在单个应用程序中,用SQLitepipe理许多项目。 我想要的是为我的应用程序正在pipe理的每个项目都有一个不同的数据库..所以多个相同结构的数据库的副本,但其中有不同的数据。 我将select基于URI上的参数使用哪个副本。
这是为安全完成的..我是这种编程newbe,我不希望它发生,因为某种原因,而在一个项目上工作,另一个被损坏.. 2.容易备份和归档旧项目
Rails默认不是为多数据库体系结构devise的,在大多数情况下,它根本没有意义。 但是,是的,你可以使用不同的数据库和连接。
这里有一些参考:
- ActiveRecord:连接到不同模型中的多个数据库
- Ruby on Rails中的多个数据库连接
- 魔术多连接
如果您能够控制和configuration每个Rails实例,并且您可以承担浪费的资源,因为它们处于待机状态,请省去一些麻烦,只需更改database.yml即可修改每个实例使用的数据库连接。 如果你关心性能这个方法不会削减它。
对于仅在一个数据库上绑定到单个唯一表的模型,可以调用模型内的establish_connection:
establish_connection "database_name_#{RAILS_ENV}"
如下所述: http : //apidock.com/rails/ActiveRecord/Base/establish_connection/class
您将有一些模型使用来自一个数据库的表格和其他不同的模型使用来自其他数据库的表格。
如果你有相同的表,不同的数据库是共同的,并由一个模型共享,ActiveRecord不会帮助你。 早在2009年,我就需要使用Rails 2.3.8开发一个项目。 我有一个每个客户的数据库,我用他们的ID命名数据库。 所以我创build了一个方法来改变ApplicationController中的连接:
def change_database database_id = params[:company_id] return if database_id.blank? configuration = ActiveRecord::Base.connection.instance_eval { @config }.clone configuration[:database] = "database_name_#{database_id}_#{RAILS_ENV}" MultipleDatabaseModel.establish_connection configuration end
并将该方法作为before_filter添加到所有控制器中:
before_filter :change_database
因此,对于每个控制器的每个动作,当params [:company_id]被定义和设置时,它会将数据库更改为正确的。
为了处理迁移,我扩展了ActiveRecord :: Migration,使用一种查找所有客户的方法,并用每个ID迭代一个块:
class ActiveRecord::Migration def self.using_databases *args configuration = ActiveRecord::Base.connection.instance_eval { @config } former_database = configuration[:database] companies = args.blank? ? Company.all : Company.find(args) companies.each do |company| configuration[:database] = "database_name_#{company[:id]}_#{RAILS_ENV}" ActiveRecord::Base.establish_connection configuration yield self end configuration[:database] = former_database ActiveRecord::Base.establish_connection configuration end end
请注意,通过这样做,您不可能在两个不同的数据库的同一个操作中进行查询。 您可以再次调用change_database ,但是当您尝试使用执行查询的方法时,会从不再链接到正确的数据库的对象中变得很讨厌。 另外,显然你不能连接属于不同数据库的表。
要正确处理这个问题,ActiveRecord应该大大扩展。 现在应该有一个插件来帮助你解决这个问题。 一个快速的研究给了我这个:
DB-Charmer: http : //kovyrin.github.com/db-charmer/
我愿意尝试。 让我知道什么适合你。
我通过将其添加到使用其他数据库的模型的顶部来解决这个问题
class Customer < ActiveRecord::Base ENV["RAILS_ENV"] == "development" ? host = 'devhost' : host = 'prodhost' self.establish_connection( :adapter => "mysql", :host => "localhost", :username => "myuser", :password => "mypass", :database => "somedatabase" )
你也应该看看这个叫做DB Charmer的项目: http : //kovyrin.net/2009/11/03/db-charmer-activerecord-connection-magic-plugin/
DbCharmer是一个简单而强大的ActiveRecord插件,可以做几件事情:
- 允许您轻松pipe理AR模型的连接(
switch_connection_to
方法)- 允许您将AR模型的默认连接切换到单独的服务器/数据库
- 允许您轻松地select查询的位置(
on_*
方法系列)- 允许您自动发送读取查询到您的奴隶,而主人将处理所有的更新。
- 将多个数据库迁移添加到ActiveRecord
值得注意的是,在所有这些解决scheme中,您需要记住closures自定义数据库连接。 你将用完连接,否则看到奇怪的请求超时问题。
一个简单的解决办法是clear_active_connections! 在你的控制器的after_filter。
after_filter :close_custom_db_connection def close_custom_db_connection MyModelWithACustomDBConnection.clear_active_connections! end
在你的config / database.yml中做这样的事情
default: &default adapter: postgresql encoding: unicode pool: 5 development: <<: *default database: mysite_development test: <<: *default database: mysite_test production: <<: *default host: 10.0.1.55 database: mysite_production username: postgres_user password: <%= ENV['DATABASE_PASSWORD'] %> db2_development: <<: *default database: db2_development db2_test: <<: *default database: db2_test db2_production: <<: *default host: 10.0.1.55 database: db2_production username: postgres_user password: <%= ENV['DATABASE_PASSWORD'] %>
那么在你的模型中你可以引用db2
class Customers < ActiveRecord::Base establish_connection "db2_#{Rails.env}".to_sym end