If you have decided to create an API, there are several questions to ask. One of them is what style of API you will use. The Ruby on Rails community has rallied around the idea of REST—"representational state transfer", a term coined by Roy Fielding—which basically assumes that each URL uniquely identifies a resource on the Internet. Different actions performed on that resource do not make use of different URLs, but rather of different HTTP request methods.
For example, if you have an address book containing information on many people, the first entry might have a URL of:
In such a case, you could retrieve information with:
and a new entry with:
Remember that POST requests send their name-value pairs separately from the URL. Because the parameters aren't part of the URL, it sometimes can be a bit tricky to know precisely what is being sent to the server. I generally check the parameters that are being sent using a combination of tools, including the server's logfile, the Firebug plugin for Firefox, the Web developer plugin for Firefox or the ngrep command-line tool for finding and displaying selected network packets.
In the Ruby on Rails universe, you can update an existing entry using the little-known (and little-supported, at least for now) PUT request method:
As with POST, the parameters in a PUT request are sent separately from the URL. Trickier yet is the fact that many browsers cannot handle PUT requests directly. The solution that Rails employs, for the time being, is to use POST, but to add a "_method" parameter as part of the request. When the server sees this, it uses the action that should be associated with PUT, rather than with POST. The system works well, although it obviously would be better if browsers were able to support all of the standard HTTP requests.
One of the key things to remember when working with REST is that URLs should refer to nouns, not verbs. Thus, it's perfectly acceptable, within the REST world, to have URLs that refer to any object on your system, from users to books to airplanes to credit-card statements. However, it's not acceptable to name the action you wish to take in the URL. So:
would be perfectly acceptable, but:
would not be. The difference being, of course, that get_passenger_list is presumably the name of an action that you wish to take on the airplane resource. This means you're no longer using the URL to refer to a specific resource, but instead to an action.
When it was announced that Rails was moving toward REST, I must admit I was somewhat resistant. I preferred to use URLs that had been traditional in the Rails world until then, naming the controller and action, as well as an object ID, in the URL. Thus, if I wanted to retrieve one person's address, I would use a URL such as:
where 2341 would be the unique ID for that person. And, for the most part, this paradigm worked just fine.
But, then I discovered what many Rails developers find out: that Rails is, as it claims to be, "opinionated" software, meaning that things are extremely easy if you do them the way it was designed, and very difficult if you try it in any other way. And as time went on, it became clear that my non-REST URLs were giving me problems. Many elements of Rails were no longer working for me, because they depended on REST. When I started to work with Backbone.js in 2011, I found that Backbone works with a variety of back ends, including Rails, but that using a non-REST interface was clumsy to work with, if it was even possible to use at all.
Thus, I began to get REST religion and tried to make every application I wrote conform to this sort of API, and it worked in many ways. The APIs were consistent, and my code was consistent. Because I was using the scaffolding that Rails provided—if only at the start of a project—the code was smaller and more consistent than otherwise would have been the case. In the case of Rails, which dynamically creates identifiers that represent specific URLs (for example, addresses), sticking with the RESTful routes really simplified things.
That is, until it didn't do so. REST, at least in the Rails implementation, gives you a single HTTP request method for each action you want to perform on your resource. This works well, in my experience, until you want to retrieve resources based on parameters, at which point things can get a bit complicated. Sure, you can pass parameters in the HTTP request, but at a certain point, I personally would rather have several small methods than one method with a huge set of if-then statements reflecting different combinations of parameters.
Reuven M. Lerner, Linux Journal Senior Columnist, a longtime Web developer, consultant and trainer, is completing his PhD in learning sciences at Northwestern University.
Free DevOps eBooks, Videos, and more!
Regardless of where you are in your DevOps process, Linux Journal can help!
We offer here the DEFINITIVE DevOps for Dummies, a mobile Application Development Primer, and advice & help from the expert sources like:
- Linux Journal
Web Development News
- Promise Theory—What Is It?
- Integrating Trac, Jenkins and Cobbler—Customizing Linux Operating Systems for Organizational Needs
- New Products
- New Products
- RSS Feeds
- Tech Tip: Really Simple HTTP Server with Python
- EdgeRouter Lite
- Non-Linux FOSS: Remember Burning ISOs?
- Raspberry Pi: the Perfect Home Server