Легко использовать open-uri и Net :: HTTP. Ну, легкий это относительный термин. Создание клиентской библиотеки для доступа к нашей службе диспетчера задач все еще потребует значительного количества стандартного кода, больше, чем мы хотим написать, протестировать и поддерживать. Мы также показали вам некоторые принципы и соглашения для разработки Web-сервисов RESTful, и в этой заключительной части нашей серии из трех частей мы сделаем еще один шаг вперед и покажем, как мы можем использовать их для разработки клиентской библиотеки для менеджера задач с использованием ActiveResource.
Если вы пропустили первую и вторую части серии, вы можете найти их здесь:
Эта серия статей основана на главе 5 из Ruby in Practice Джереми МакАнелли и Ассаф Аркин. Предоставлено Manning Publications . Все права защищены.
ПРОБЛЕМА
[img_assist | nid = 4838 | title = | desc = | link = url | url = http: //www.manning.com/mcanally/ | align = right | width = 139 | height = 174] При работающей службе диспетчера задач Пришло время двигаться вперед и разрабатывать наше приложение рабочего процесса, и как часть этого приложения нам нужно будет создавать задачи и управлять ими. Мы хотим повторно использовать нашу службу диспетчера задач, и мы хотим сделать это до конца дня.
РЕШЕНИЕ
Мы собираемся создать клиентское приложение, которое использует службу диспетчера задач, используя ActiveResource. Начнем с написания класса, представляющего ресурсы для обработки списка задач и отдельных задач:
class Task < ActiveResource::Base
self.site = 'https://john:[email protected]/'
end
Мы используем URL-адрес, чтобы указать имя пользователя / пароль для доступа к службе, и они сопоставляются с HTTP Basic Authentication, используя HTTPS, когда нам нужно получить доступ к нему через публичные сети. Мы еще не написали ни одной строки кода, но давайте сначала посмотрим, что мы можем сделать с нашим новым классом Task. Давайте начнем с создания новой задачи:
task = Task.create(:title=>'Read about ActiveResource', :priority=>1)
puts 'Created task #{task.id}'
=> 'Created task 1'
Разве этот код не выглядит очень знакомым? Мы используем ActiveResource для работы с удаленными ресурсами, но шаблоны такие же, как и в предыдущем разделе, где мы использовали ActiveRecord для доступа к базе данных. Давайте посмотрим, что происходит за кулисами метода create:
task = Task.new
task.title = 'Read about ActiveResource'
task.priority = 1
task.save
Он начинается с создания нового объекта в памяти и установки его атрибутов и сохраняет объект, отправляя запрос POST к ресурсу / задачам с документом XML, содержащим определение задачи. Наша простая реализация получает XML-документ, анализирует атрибуты и использует их для создания записи в базе данных. Затем он сообщает клиенту, что такое новый ресурс задачи, и это все, что нужно знать нашему ActiveResource. Давайте продолжим, обновив задачу:
task.title << ' and try this example'
task.save
На этот раз, поскольку задача уже существует, мы делаем PUT-запрос к ресурсу и обновляем. Таким образом, мы можем создавать и обновлять ресурсы. Мы также можем прочитать и удалить их:
task = Task.find(1)
task.delete
tasks = Task.find(:all)
Task.delete(tasks.first.id)
Все это просто вопрос соглашений. ActiveResource следует тем же соглашениям, которые мы использовали при создании службы диспетчера задач, поэтому мы получили всю эту функциональность, просто указав URL-адрес. Как мы узнаем, что наш класс Task отправляет запросы на правильный URL? Мы предположили, что он использует XML по умолчанию, есть ли способ узнать наверняка? Давайте попробуем эквивалент задачи рейка маршрутов:
puts Task.collection_path
=> /tasks.xml
puts Task.element_path(1)
=> /tasks/1.xml
Мы построили наш диспетчер задач по всему общему шаблону, но также добавили два ресурса, специфичных для нашего диспетчера задач. У нас был один ресурс для перечисления всех выполненных задач, и мы также хотим использовать его на нашем клиенте, поэтому давайте перечислим их:
Task.find(:all, :from=>:completed)
Как вы можете догадаться, это просто запрос к пути /tasks/completed.xml. У нас также был ресурс для быстрого обновления приоритета задачи, который мы разработали для поддержки наших элементов управления AJAX. Давайте попробуем использовать это также:
task.put(:priority, nil, 5)
На этот раз запрос отправляется в / tasks / {id} / priority, заменяя идентификатор задачи в шаблоне URL. Метод put принимает два дополнительных аргумента, первый из которых представляет собой хеш, который передается в качестве параметров строки запроса, а второй — тело сообщения. Мы передаем номер приоритета в теле сообщения.
Как и следовало ожидать, есть и другие пользовательские методы, такие как get, post и delete. Мы собираемся скрыть детали put из приложения, обернув его в метод; на самом деле, мы добавим еще пару для создания класса ActiveResource, который представляет нашу службу диспетчера задач.
class Task < ActiveResource::Base
self.site = 'https://taskmanager.example.com/'
def self.completed
find(:all, :from=>:completed)
end
def self.update_priority(id, value)
Task.new(:id=>id).priority!(value)
end
def priority!(value)
put(:priority, nil, value.to_i)
end
end
Теперь давайте попробуем это:
Task.site.user_info = 'john:secret'
puts 'Completed tasks'
puts Task.completed.map { |task| task.id }.to_sentence
=> "1, 2 and 3"
puts 'Changing priority for task 123'
Task.update_priority(123, 5)
puts Task.find(123).priority
=> 5
ОБСУЖДЕНИЕ
Как вы видели из наших примеров, Rails чрезвычайно облегчает создание веб-сервисов, которые следуют принципам REST и одинаково хорошо работают с веб-браузерами и программируемым веб-интерфейсом. На самом деле, большая часть этой простоты проистекает из следования этим принципам. Нам не нужно было указывать нашему клиенту, как создавать, читать, обновлять или удалять ресурс, все они использовали надлежащие методы HTP. Все, что нам нужно было сделать, это направить нашего клиента в нужное место. Точно так же нам не нужно было создавать два разных приложения диспетчера задач: одно, которое люди могли бы использовать, а другое — для обслуживания приложений. Мы управляли обоими одновременно, используя разные типы контента.
Если вы будете следовать соглашениям Rails, вы получите базовые операции CRUD бесплатно. На практике этого часто недостаточно, и вы обнаружите, что вам нужны более конкретные ресурсы и дополнительные действия в контроллерах. Мы показали, как легко добавить эти пользовательские методы как на стороне сервера, так и на стороне клиента. Есть, конечно, другие вещи, которые вам нужно сделать, полнофункциональный менеджер задач должен обрабатывать крайние сроки и исключения, отправлять уведомления, даже порождать рабочие процессы, которые будут включать еще больше задач и взаимодействовать с другими сервисами. Это все возможно сделать в рамках ограничений REST.
В последних трех решениях мы много говорили о Rails, но мы хотим, чтобы это были уроки, которые вы можете взять с собой, если будете использовать другие веб-фреймворки или даже другие языки программирования. Одним из них была рекомендуемая практика создания веб-сервисов RESTful и преимущества, которые дает следование стилю архитектуры REST. Другим преимуществом стало понимание соглашений и того, как они могут помочь вам лучше проектировать, разрабатывать быстрее и в конечном итоге получить код, который легче понять и поддерживать. Если ничего другого, было бы меньше, чтобы документировать. Соглашения не только для Rails, когда вы создаете собственное приложение, подумайте, как соглашения могут помочь вам работать меньше и делать больше.
Протокол обмена сообщениями SOAP — это еще один способ использования протокола HTTP и создания служб, которые взаимодействуют с языками, платформами и приложениями.