Asterisk™: будущее телефонии Второе издание
Шрифт:
Интеграция с базами данных
Несмотря на чрезвычайный успех в области веб-разработки для обслуживания динамического содержимого, интеграция с базами данных всегда была и остается недостаточно реализованной возможностью управления динамическими голосовыми приложениями в Asterisk. Большинство приложений Asterisk, выполняющих интеграцию с базами данных, делегируют реализацию сложных вопросов AGI-сценариям на
PHP или Perl, потому что extensions.conf или синтаксиса AEL просто недостаточно для решения задач такого уровня сложности. Adhearsion использует библиотеку интеграции с базами данных ActiveRecord, разработанную создателями
'id' int(11) DEFAULT NULL auto_increment PRIMARY KEY, 'description' varchar(255) DEFAULT NULL, 'hourly_rate' decimal DEFAULT NULL
);
CREATE TABLE customers (
'id' int(11) DEFAULT NULL auto_increment PRIMARY KEY, 'name' varchar(255) DEFAULT NULL, 'phone_number' varchar(10) DEFAULT NULL, 'usage_this_month' int(11) DEFAULT 0, 'group_id' int(11) DEFAULT NULL
);
В реальности, конечно, о заказчике хранилось бы намного больше сведений и информация об использовании сервиса находилась бы в записи параметров вызова в базе данных, но такое упрощение позволяет более эффективно продемонстрировать основные моменты ActiveRecord. Чтобы подключить Adhearsion к этой базе данных, необходимо просто задать информацию для доступа к базе данных в конфигурационном файле YAML: adapter: mysql host: localhost database: adhearsion username: root password: pass
Так Adhearsion будет знать, как подключиться к базе данных, однако механизм доступа к информации в таблицах зависит от того, как смоделированы наши объекты ActiveRecord. Поскольку объект - это экземпляр класса, для каждой таблицы ставим в соответствие класс. С помощью методов надкласса определяем простые свойства и отношения в классе.
Вот два класса, которые могут использоваться с вышеупомянутыми таблицами:
class Customer < ActiveRecord::Base belongs_to :group
validates_presence_of :name, :phone_number validates_uniqueness_of :phone_number validates_associated :group def total_bill
self.group.hourly_rate * self.usage_this_month / 1.hour end
end
class Group < ActiveRecord::Base has_many :customers
validates_presence_of description, :hourly_rate
end
Уже из этого небольшого объема информации ActiveRecord может сделать множество логических выводов. При обработке данных классов ActiveRecord переводит их имена в нижний регистр, ставит во множественное число и принимает, что это - имена таблиц (customers и groups соответственно). Если применение такого соглашения нежелательно, автор может без труда переопределить его. Кроме того, во время интерпретации ActiveRecord на самом деле заглядывает в столбцы базы данных и делает доступными многие новые создаваемые динамически методы.
Методы belongs_to (принадлежит) и has_many (имеет много) в данном примере определяют отношения между Customers (клиенты) и Groups (группы). Опять обратите внимание, как ActiveRecord использует множественное число в строке has_many :customers
Также обратите внимание на метод total_bill (общий счет) класса Customer. Для любого объекта Customer, извлекаемого из базы данных, можно вызвать этот метод, который умножает значение hourly_rate для группы, к которой принадлежит Customer, на время пользования телефоном этого клиента (в секундах).
Вот несколько примеров, которые могут точнее продемонстрировать то, насколько удобно применять абстрактную объектную логику Ruby для работы с базами данных:
everyone = Customer.find :all
jay = Customer.find_by_name "Jay Phillips"
jay.phone_number # Выполняем выражение SELECT
jay.total_bill # Выполняем вычисления по нескольким выражениям SELECT
jay.group.customers.average :usage_this_month jay.group.destroy
jay.group = Group.create description => "New cool group!",
:hourly_rate => 1.23
jay.save
Интеграция с базой данных стала здесь намного более естественной, а диалпланы Asterisk выглядят более выразительными. Ниже представлен пример диалплана поставщика сервисов, который налагает ограничение на суммарную продолжительность исходящих звонков, используя информацию из базы данных. Постараемся сохранить простоту:
# Предположим, сервис VoIP предлагается клиентам,
# которые могут быть идентифицированы по их callerid.
service {
# Строка кода ниже реализует выражение SQL SELECT
# по отношению к нашей базе данных. Метод
# find_by_phone_number был создан автоматически,
# потому что ActiveRecord обнаружила в базе данных
# столбец phone_number. Adhearsion создает для нас
# переменную callerid.
caller = Customer.find_by_phone_number callerid
usage = caller.usage_this_month if usage >= 100.hours
play "sorry-cant-let-you-do-that" else
play %w'to-hear-your-account-balance press-1
otherwise wait-moment' choice = wait_for_digit 3.seconds
p choice if choice == 1
charge = usage / 60.0 * caller.group.hourly_rate play %W"your-account will-reflect-charge-of
$#{charge} this month for #{usage / 60} minutes and #{usage % 60} seconds"
end
# Мы также можем записать значение свойства
# usage_this_month объекта caller. По завершении
# выполнения метода time новое значение для этого
# абонента будет внесено в базу данных. caller.usage_this_month += time do
# Засекаем время выполнения данного фрагмента кода. dial IAX/'main-trunk'/extension
end
caller.save
end
Надежная интеграция с базой данных, которую обеспечивает Adhear- sion, упрощает управление и разработку для офисной АТС. Хранящаяся централизованно информация позволяет Asterisk напрямую интегрироваться с другими сервисами, обеспечивая при этом более ценные сервисы, которые не могут быть реализованы в рамках традиционных технологий разработки в Asterisk.