DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Last call! Secure your stack and shape the future! Help dev teams across the globe navigate their software supply chain security challenges.

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workloads.

Releasing software shouldn't be stressful or risky. Learn how to leverage progressive delivery techniques to ensure safer deployments.

Avoid machine learning mistakes and boost model performance! Discover key ML patterns, anti-patterns, data strategies, and more.

Related

  • Building REST API Backend Easily With Ballerina Language
  • Hybris Multi-Tenant System Using REST Webservices
  • What Are SpeedUp and ScaleUp in DBMS?
  • Flex for J2EE Developers: The Case for Granite Data Services

Trending

  • Beyond ChatGPT, AI Reasoning 2.0: Engineering AI Models With Human-Like Reasoning
  • Why High-Performance AI/ML Is Essential in Modern Cybersecurity
  • Top Book Picks for Site Reliability Engineers
  • Intro to RAG: Foundations of Retrieval Augmented Generation, Part 1
  1. DZone
  2. Data Engineering
  3. Databases
  4. How To REST With Rails and ActiveResource: Part Three

How To REST With Rails and ActiveResource: Part Three

Part 3 shows how to use principles and conventions for designing RESTful Web services to develop a client library for the task manager using ActiveResource.

By 
Schalk Neethling user avatar
Schalk Neethling
·
Updated Jun. 18, 22 · News
Likes (1)
Comment
Save
Tweet
Share
28.5K Views

Join the DZone community and get the full member experience.

Join For Free

It’s easy to use OpenURI and Net::HTTP. Well, "easy" is a relative term. Building a client library to access our task manager service still requires a fair amount of boilerplate code — more than we care to write, test, and maintain. We have shown you some principles and conventions for designing RESTful web services, and in this final part of our three-part series, we'll take it a step further and show you how we can use them to develop a client library for the task manager using ActiveResource.

If you missed parts one and two of the series you can find them here:

  1. How To REST With Rails and ActiveResource: Part One

  2. How To REST With Rails and ActiveResource: Part Two

This article series is based on chapter 5 from Ruby in Practice by Jeremy McAnally and Assaf Arkin. Courtesy of Manning Publications. All rights reserved.

Problem

With the task manager service up and running, it's time to move forward and develop our workflow application. And as part of that application, we'll need to create and manage tasks. We want to reuse our task manager service, and we want to get it done before the day is over.

Solution

We're going to build a client application that uses the task manager service using ActiveResource. We'll start by writing a class to represent the resources for handling a task list and individual tasks:

class Task < ActiveResource::Base
self.site = 'https://john:secret@taskmanager.example.com/'
end


We're using the URL to specify the username/password for accessing the service. These map to HTTP Basic Authentication using HTTPS when we need to access it over public networks. We've yet to write a single line of code, but let's first see what we can do with our new Task class. Let's start by creating a new task:

task = Task.create(:title=>'Read about ActiveResource', :priority=>1)
puts 'Created task #{task.id}'
=> 'Created task 1'


Doesn't this code look awfully familiar? We're using ActiveResource here to operate against remote resources, but the patterns are the same as in the previous section, where we used ActiveRecord to access the database. Let's see what happens behind the scenes of the create method:

task = Task.new
task.title = 'Read about ActiveResource'
task.priority = 1
task.save


It starts by creating a new object in memory and setting its attributes. It saves the object by making a POST request to the resource/tasks with an XML document containing the task definition. Our simple implementation receives the XML document, parses the attributes, and uses them to create a record in the database. It then tells the client what the new task resource is, which is all our ActiveResource needs to know. Let's follow up by updating the task:

task.title << ' and try this example'
task.save


This time, since the task already exists, we make a PUT request to the resource and update, so we can create and update resources. We can also read and delete them:

task = Task.find(1)
task.delete
tasks = Task.find(:all)
Task.delete(tasks.first.id)


All of this is just a matter of conventions. ActiveResource follows the same conventions we used when we built the task manager service, so we got all this functionality just by specifying a URL. How do we know our Task class sends requests to the right URL? We assumed it uses XML by default. Is there a way to find out for sure? Let's try the equivalent of the rake routes task:

puts Task.collection_path
=> /tasks.xml
puts Task.element_path(1)
=> /tasks/1.xml


We built our task manager around all the common patterns but also added two resources specific to our task manager. We had one resource for listing all the completed tasks. We'll want to use that from our client as well, so let's list those:

Task.find(:all, :from=>:completed)


As you can guess, this just is a request against the /tasks/completed.xml path. We also had a resource for quickly updating the task priority, which we designed to support our Ajax controls. Let's try to use that as well:

task.put(:priority, nil, 5)


This time, the request goes to /tasks/{id}/priority, substituting the task identifier in the URL template. The put method takes two additional arguments. The first is a hash that is passed along as query string parameters, and the second is the body of the message. We're passing a priority number in the body of the message.

As you can expect, there are other custom methods you can use like get, post, and delete. We're going to hide the details of put from the application by wrapping it in a method; in fact, we'll add a couple more to create an ActiveResource class that represents our task manager service.

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


Now let's try it out:

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


Discussion

As you’ve seen from our examples, Rails makes it extremely easy to build web services that follow the REST principles and work equally well with web browsers and the programmable Web. In fact, a lot of that simplicity comes directly from following these principles. We didn’t have to tell our client how to create, read, update or delete the resource: those all followed by using the proper HTTP methods. All we had to do is point our client at the right place. Likewise, we didn’t have to build two task manager applications (one that people can use and another for service applications). We managed both at the same time by using different content types.

If you follow Rails conventions, you get the basic CRUD operations for free. In practice, that’s often not enough, and you’ll find that you need more specific resources and layering additional actions into your controllers. We showed you how easy it is to add these custom methods on both the server and the client-side. There are, of course, other things you’ll need to do. A fully functional task manager would need to handle deadlines and exceptions, send notifications, and even spawn workflows that would involve even more tasks and interact with other services. Those are all possible to do within the constraints of REST.

In the last three solutions, we talked extensively about Rails, but we want those to be lessons you can take with you if you use other web frameworks or even other programming languages. One was the recommended practice for building RESTful web services and the benefit that comes from following the REST architecture style. The other was the benefit of picking up on conventions and how they can help you design better, develop faster and end up with code that’s easier to understand and maintain. If nothing else, there would be less to document. Conventions are not just for Rails: when you’re building your own application, think about how conventions could help you work less and get more done.

The SOAP messaging protocol is another way to harness the HTTP protocol and build services that cross languages, platforms, and applications.

Task (computing) Database Web Service application REST

Opinions expressed by DZone contributors are their own.

Related

  • Building REST API Backend Easily With Ballerina Language
  • Hybris Multi-Tenant System Using REST Webservices
  • What Are SpeedUp and ScaleUp in DBMS?
  • Flex for J2EE Developers: The Case for Granite Data Services

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!