在rails应用程序中,我的代码是纯ruby:
class LinkCreator
attr_accessor :animal
def initialize(animal:)
@animal = animal
end
def call
"something#{link_id}"
end
private
def link_id
connection.execute(sql_request).first.first
end
def sql_request
"SELECT field FROM table WHERE field_id = '#{field_id}' LIMIT 1"
end
def field_id
animal.field_id
end
def connection
ActiveRecord::Base.establish_connection(
adapter: "mysql",
host: ENV["MYSQL_HOST"],
username: ENV["MYSQL_USERNAME"],
password: ENV["MYSQL_PASSWORD"],
database: ENV["MYSQL_DB_NAME"]
).connection
end
end
正如您所看到的,这不是一个模型,而只是一个简单的类。问题在于,更改了activerecord的连接,以及稍后在新连接上执行的其他请求。
是否可以仅在块中建立连接并返回旧连接。我知道我可以建立另一个连接,但这对性能非常不利。
答案 0 :(得分:18)
如果您将所有数据库连接保留在database.yml
development:
adapter: mysql2
other stuff...
db_2:
adapter: mysql2
other stuff..
other_envs:
.....
然后创建一个类
class OtherDB < ActiveRecord::Base
establish_connection(:db_2)
end
您可以从控制器访问
OtherDB.table_name = "table_name"
OtherDB.first
答案 1 :(得分:8)
您可以在一个区块内执行一些查询。首先,定义一些扩展ActiveRecord的模块,如下所示。这是生产中用于更改每个请求的数据库连接以及临时切换数据库以在另一个数据库中执行某些查询的代码的一部分。
# RAILS_ROOT/lib/connection_switch.rb
module ConnectionSwitch
def with_db(connection_spec_name)
current_conf = ActiveRecord::Base.connection_config
begin
ActiveRecord::Base.establish_connection(db_configurations[connection_spec_name]).tap do
Rails.logger.debug "\e[1;35m [ActiveRecord::Base switched database] \e[0m #{ActiveRecord::Base.connection.current_database}"
end if database_changed?(connection_spec_name)
yield
ensure
ActiveRecord::Base.establish_connection(current_conf).tap do
Rails.logger.debug "\e[1;35m [ActiveRecord::Base switched database] \e[0m #{ActiveRecord::Base.connection.current_database}"
end if database_changed?(connection_spec_name, current_conf)
end
end
private
def database_changed?(connection_spec_name, current_conf = nil)
current_conf = ActiveRecord::Base.connection_config unless current_conf
current_conf[:database] != db_configurations[connection_spec_name].try(:[], :database)
end
def db_configurations
@db_config ||= begin
file_name = "#{Rails.root}/config/database.yml"
if File.exists?(file_name) || File.symlink?(file_name)
config ||= HashWithIndifferentAccess.new(YAML.load(ERB.new(File.read(file_name)).result))
else
config ||= HashWithIndifferentAccess.new
end
config
end
end
end
ActiveRecord.send :extend, ConnectionSwitch
现在您可以按如下方式使用它:
ActiveRecord.with_db("db_connection_name") do
# some queries to another db
end
答案 2 :(得分:5)
在activerecord/test/support/connection_helper.rb的Rails代码库中找到了最简短的例子,稍微适应了:
def with_another_db(another_db_config)
original_connection = ActiveRecord::Base.remove_connection
ActiveRecord::Base.establish_connection(another_db_config)
yield
ensure
ActiveRecord::Base.establish_connection(original_connection)
end
用法(假设您another_db:
中有database.yml
部分):
with_another_db(ActiveRecord::Base.configurations['another_db']) do
ActiveRecord::Base.connection.execute("SELECT 'Look ma, I have changed DB!';")
end
答案 3 :(得分:2)
我使用Heroku&#39; DATABASE_URL
中的环境变量连接到不同的数据库:
class Database
def self.development!
ActiveRecord::Base.establish_connection(:development)
end
def self.production!
ActiveRecord::Base.establish_connection(ENV['PRODUCTION_DATABASE'])
end
def self.staging!
ActiveRecord::Base.establish_connection(ENV['STAGING_DATABASE'])
end
end
e.g:
Database.production!; puts User.all.map(&:name)
Database.staging!; puts User.all.map(&:name)
答案 4 :(得分:0)
使用实例变量来存储连接可能会有所帮助。像这样:
def connection
@connection ||= ActiveRecord::Base.establish_connection(
adapter: "mysql",
host: ENV["MYSQL_HOST"],
username: ENV["MYSQL_USERNAME"],
password: ENV["MYSQL_PASSWORD"],
database: ENV["MYSQL_DB_NAME"]
).connection
end
这样就可以在将来的连接尝试中检索现有连接,而不是建立新连接。
答案 5 :(得分:0)
如果要连接到postgres sql,可以使用pg ruby gem并将下面的代码添加到代码块中。
postgres = PG.connect :host => <host_name>, :port => <port>, :dbname => <database_name>, :user => <user>, :password => <password>
tables = postgres.exec(query)
tables.num_tuples.times do |i|
print tables[i]
end
要连接到块内的mysql db,请使用mysql2 ruby gem并在块内添加以下代码。
db = Mysql2::Client.new ActiveRecord::ConnectionAdapters::ConnectionSpecification::ConnectionUrlResolver.new(<database_url>).to_hash
data = db.query(<<-SQL)
select * from students
SQL
print data
答案 6 :(得分:0)
尝试 active_record_slave 宝石: