возвращает идентификатор строки, соответствующей новой записи (вы можете использовать его или игнорировать). Это «скрытое» автоинкрементное поле, присутствующее в каждой записи любой таблицы. Для выборки записей служит метод
select
. Без параметров он выбирает все поля всех записей таблицы. Набор полей можно ограничить, передав в качестве параметров символы. Если задан блок, то он определяет, какие записи отбирать (примерно так же, как работает метод
find_all
для массивов).
list1 = people.select #
Все люди, все поля.
list2 = people.select(:name,:age) # Все люди, только имя и возраст.
В блоке допустимы любые операции. Это означает, например, что можно формулировать запрос с помощью регулярных выражений (в отличие от типичной SQL-базы).
Результирующий набор, возвращаемый KirbyBase, можно сортировать по нескольким ключам в порядке возрастания или убывания. Для сортировки по убыванию перед именем ключа ставится минус. (Это работает, потому что в класс
Symbol
добавлен метод, соответствующий унарному минусу.)
sorted = people.select.sort(:name,-:age)
# Отсортировать в порядке возрастания name и в порядке убывания age.
У результирующего набора есть одно интересное свойство: он может предоставлять массивы, «срезающие» результат. С первого раза это довольно трудно понять.
Предположим, что есть результирующий набор записей, представляющих людей, и в каждой записи хранятся имя, возраст, рост и вес. Понятно, что этот результирующий набор можно индексировать как массив, но одновременно он имеет методы, названные так же, как поля. Каждый такой метод возвращает массив значений только соответствующего ему поля. Например:
list = people.select(:name,:age,:heightweight)
p list[0] # Вся информация о человеке 0.
p list[1].age # Только возраст человека 1.
p list[2].height # Рост человека 2.
ages = list.age # Массив: возрасты всех людей.
names = list.name # Массив: имена всех людей.
В KirbyBase есть ограниченные средства печати отчетов; достаточно вызвать метод
# 2 | Democracy in America | Alexis de Tocqueville
# 1 | The Case for Mars | Robert Zubrin
# 3 | The Ruby Way | Hal Fulton
Атрибут таблицы
encrypt
можно установить в
true
— тогда данные нельзя будет читать и редактировать, как обычный текст. Но имейте в виду, что для этого применяется шифр Вигенера — не «игрушечный», но и не являющийся криптографически безопасным. Так что пользоваться шифрованием имеет смысл только для
того, чтобы помешать редактированию, но никак не для сокрытия секретных данных. Обычно режим шифрования устанавливается в блоке при создании таблицы:
Поскольку удаленный доступ — интересное средство, уделим ему немного внимания. Вот пример сервера:
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|