в Rails, как мне выполнить прямой SQL-код в другой базе данных?
-
09-06-2019 - |
Вопрос
Вот такой случай.
Я пишу приложение Rails, которое будет отслеживать качество данных в некоторых конкретных базах данных.Чтобы сделать это, мне нужно иметь возможность выполнять прямые SQL-запросы к этим базам данных, которые, конечно, не совпадают с теми, которые используются для управления моделями приложений Rails.Короче говоря, это означает, что я не могу использовать трюк с прохождением через базовое соединение ActiveRecord.
Базы данных, к которым мне нужно подключиться, неизвестны во время разработки (т. е.:Я не могу поместить их данные в database.yaml).Скорее, у меня есть модель "database_details", которую пользователь будет использовать для ввода сведений о базах данных, по которым приложение будет выполнять запросы во время выполнения.
Таким образом, подключение к этим базам данных действительно является динамическим, и детали разрешаются только во время выполнения.
Как я могу это сделать?
Спасибо,
Ролло
Решение
У меня была подобная ситуация, когда мне пришлось подключаться к сотням различных экземпляров внешнего приложения, и я выполнил код, подобный следующему:
def get_custom_connection(identifier, host, port, dbname, dbuser, password)
eval("Custom_#{identifier} = Class::new(ActiveRecord::Base)")
eval("Custom_#{identifier}.establish_connection(:adapter=>'mysql', :host=>'#{host}', :port=>#{port}, :database=>'#{dbname}', " +
":username=>'#{dbuser}', :password=>'#{password}')")
return eval("Custom_#{identifier}.connection")
end
Это имеет дополнительное преимущество в том, что вы не изменяете ваше соединение ActiveRecord ::Base, от которого наследуются ваши модели, поэтому вы можете запустить SQL для этого соединения и удалить объект, когда закончите с ним.
Другие советы
Вы можете программно установить соединение, используя подобный вызов
ActiveRecord::Base.establish_connection(
:adapter => "mysql",
:host => "localhost",
:username => "myuser",
:password => "mypass",
:database => "somedatabase"
)
Как вы видите, вы можете заменить somedatabase значением database_model.database_name.то же самое с adatpter и всем прочим
ActiveRecord::Документация Base.establish_connection
Тогда вы можете использовать
ActiveRecord::Base.find_by_sql("select * ")
чтобы выполнить ваш sql-запрос.
ActiveRecord::Документация Base.find_by_sql
Мистер Мэтт был прав, хотя и неполон
Более подробную информацию (устаревшую, но все еще полезную для данного подхода к проектированию) можно найти здесь и не забудьте повторно подключиться к обычной базе данных, когда закончите :)
Возможно, вы сможете сделать это с помощью self.установить_соединение