Asterisk™: будущее телефонии Второе издание - Меггелен Джим Ван
Шрифт:
Интервал:
Закладка:
• Если необходимо воспроизводить несколько файлов последовательно, play() принимает массив имен файлов. К счастью, в Ruby есть удобный способ создания массива строковых значений (String).
Конечно, это только простой пример, демонстрирующий лишь самые основы возможностей Adhearsion для создания диалплана.
Интеграция с базами данных
Несмотря на чрезвычайный успех в области веб-разработки для обслуживания динамического содержимого, интеграция с базами данных всегда была и остается недостаточно реализованной возможностью управления динамическими голосовыми приложениями в Asterisk. Большинство приложений Asterisk, выполняющих интеграцию с базами данных, делегируют реализацию сложных вопросов AGI-сценариям на
PHP или Perl, потому что extensions.conf или синтаксиса AEL просто недостаточно для решения задач такого уровня сложности. Adhearsion использует библиотеку интеграции с базами данных ActiveRecord, разработанную создателями инфраструктуры Ruby on Rails. Имея ActiveRecord, конечный пользователь изредка, если вообще делает это, пишет SQL-выражения. А разработчик осуществляет доступ к базе данных, как к любому другому объекту Ruby. Благодаря обеспечиваемым Ruby гибкости и динамичности, доступ к базе данных выглядит и ощущается довольно естественным. Кроме того, ActiveRe- cord устраняет различия между системами управления базами данных, делая реализацию доступа к базе данных универсальной. Не вдаваясь в детали ActiveRecord и более сложные варианты ее использования, рассмотрим следующую простую схему MySQL: CREATE TABLE groups (
'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 для большей выразительности кода. В этом примере также можно увидеть несколько проверок достоверности - политик, которые будет применять ActiveRecord. При создании нового объекта Customer мы должны обеспечить для него как минимум name (имя) и phone_number (номер телефона). Задание двух телефонных номеров может привести к конфликту. У каждого Customer должна быть Group. У каждой группы должно быть description (описание) и hourly_rate (почасовая ставка). Это поможет разработчику избежать ошибок, а также нарушения целостности базы данных.
Также обратите внимание на метод 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.
Распространение и повторное использование кода
Приложение Adhearsion располагается в одной папке, поэтому полностью скопировать VoIP-приложение - не сложнее, чем архивировать файлы. Наверное, впервые в сообществе Asterisk разработчики могут запросто обмениваться друг с другом удачными приложениями и дорабатывать их. Кстати, весьма поощряется предоставление кода собственных приложений Adhearsion.
Кроме того, на локальном уровне расширения инфраструктуры Adhear- sion, называемые помощниками, могут использоваться повторно или создаваться самостоятельно. Помощниками могут быть как целые вспомогательные инфраструктуры, такие как Micromenus для интеграции с телефонными микроброузерами, так и обычный новый метод диал- плана, который возвращает выбираемые случайным образом цитаты Оскара Уайльда.