Поскольку удаленный доступ — интересное средство, уделим ему немного внимания. Вот пример сервера:
require 'kirbybase'
require 'drb'
host = 'localhost'
port = 44444
db = KirbyBase.new(:server) # Создать экземпляр базы данных.
DRb.start_service("druby://#{host} :#{port)", db)
DRb.thread.join
Это прямое применение интерфейса dRuby (см. главу 20). На стороне клиента
следует при подключении к базе данных задать символ
:client
вместо обычного
:local
.
db = KirbyBase.new(:client,'localhost',44444)
# Весь остальной код не изменяется.
Можно также выполнять обычные операции: обновлять и удалять записи, удалять таблицы и т.д. Есть и более сложные механизмы, о которых я не буду рассказывать подробно: связи один-ко-многим, вычисляемые поля и нестандартные классы записей. Подробнее см. документацию по KirbyBase на сайте RubyForge.
10.4. Подключение к внешним базам данных
Благодаря усилиям многих людей Ruby может взаимодействовать с разными базами данных, от монолитных систем типа Oracle до более скромного MySQL. Для полноты описания мы включили в него также текстовые файлы в формате CSV.
Уровень функциональности, реализованный в этих пакетах, постоянно изменяется. Обязательно познакомьтесь с последней версией документации в сети. Неплохой отправной точкой станет архив приложений Ruby.
10.4.1. Интерфейс с SQLite
SQLite — популярная база данных для тех, кто ценит программное обеспечение, которое не нужно конфигурировать. Это небольшая автономная исполняемая программа, написанная на языке С, которая хранит всю базу данных в одном файле. Хотя обычно она используется для небольших баз, но теоретически способна управиться с терабайтными объемами.
Привязка Ruby к SQLite довольно прямолинейна. API, написанный на С, обернут в класс
SQLite::API
. Поскольку при этом методы отображаются один в один и интерфейс не назовешь образцом объектной ориентированности, пользоваться этим API стоит только в случае острой необходимости.
В большинстве ситуаций вам будет достаточно класса
SQLite::Database
. Вот пример кода:
require 'sqlite'
db = SQLite::Database.new("library.db")
db.execute("select title,author from books") do |row|
p row
end
db.close
# Выводится:
# ["The Case for Mars", "Robert Zubrin"]
# ["Democracy in America", "Alexis de Tocqueville"]
# ...
Если блок не задан, то метод
execute
возвращает объект
ResultSet
(по сути, курсор, который можно перемещать по набору записей).
rs = db.execute("select title,author from books")
rs.each {|row| p row } # Тот же результат, что и выше.
rs.close
Если получен объект
ResultSet
, то программа должна будет рано или поздно закрыть его (как показано в примере выше). Если нужно обойти список записей несколько раз, то с помощью метода
reset
можно вернуться в начало. (Это экспериментальное средство, которое в будущем может измениться.) Кроме того, можно производить обход в духе генератора с помощью методов
next
и
eof?
.
rs = db.execute("select title,author from books")
while ! rs.eof?
rec = rs.next
p rec #
Тот же результат, что и выше.
end
rs.close
Методы библиотеки могут возбуждать различные исключения. Все они являются подклассами класса
SQLite::Exception
, так что легко перехватываются поодиночке или целой группой.
Отметим еще, что библиотека написана так, что может работать совместно с библиотекой
ArrayFields
Ары Ховарда (Ara Howard). Она позволяет получать доступ к элементам массива по индексу или по имени. Если перед
sqlite
затребована библиотека
arrayfields
, то объект
ResultSet
можно индексировать как числами, так и именами полей. (Но можно задать и такую конфигурацию, что вместо этого будет возвращаться объект
Hash
.)
Хотя библиотека
sqlite
вполне развита, она не покрывает всех мыслимых потребностей просто потому, что сама база данных SQLite не полностью реализует стандарт SQL92. Дополнительную информацию об SQLite и привязке к Ruby ищите в сети.
10.4.2. Интерфейс с MySQL
Интерфейс Ruby с MySQL — один из самых стабильных и полнофункциональных среди всех интерфейсов с базами данных. Это расширение, которое должно устанавливаться после инсталляции Ruby и MySQL.
Для использования модуля нужно выполнить три шага: прежде всего, загрузить модуль в свой сценарий, затем установить соединение с базой данных и, наконец, начать работать с таблицами. Для установления соединения следует задать обычные параметры: имя хоста, имя пользователя, пароль, имя базы данных и т.д.
require 'mysql'
m = Mysql.new("localhost","ruby","secret","maillist")
r = m.query("SELECT * FROM people ORDER BY name")
r.each_hash do |f|
print "#{f['name']} - #{f['email']}"
end
# Выводится что-то вроде:
# John Doe - jdoe@rubynewbie.com
# Fred Smith - smithf@rubyexpert.com
Особенно полезны методы класса
Mysql.new
и
MysqlRes.each_hash
, а также метод экземпляра
query
.
Модуль состоит из четырех классов (
Mysql
,
MysqlRes
,
MysqlField
и
MysqlError
), описанных в файле README. Мы приведем сводку некоторых наиболее употребительных методов, а дополнительную информацию вы сможете найти сами в официальной документации.
Метод класса
Mysql.new
принимает несколько строковых параметров, которые по умолчанию равны
nil
, и возвращает объект, представляющий соединение. Параметры называются
host
,
user
,
passwd
,
db
,
port
,
sock
и
flag
. У метода
new
есть синонимы
real_connect
и
connect
.
Методы
create_db
,
select_db
и
drop_db
принимают в качестве параметров имя базы данных и используются, как показано ниже. Метод