Why Do I Need to Work Harder to Make My Rails Application Fit into a Restful Architecture

What exactly is REST architecture and how is it implemented in Rails?

I think your understanding of REST is pretty good. It doesn't need to be any more complicated than it should be. Also @Surya outlines some very good points.

The way Rails maps the HTTP methods to controller methods is:

GET    => show
PUT => update
POST => create
DELETE => destroy

Two other resources/methods that rails provides namely:

resource/new  => new
resource/edit => edit

are most likely not resources for all practical purposes but are needed for building web pages and applications. If the client had full knowledge of the resource, these would not be needed. A client can just make POST and PUT calls with the resource information and create or update resources as needed. But since users are not expected to know the ins and outs of a resource, they need an easier interface to work with for creation or updation.

If all users were fully aware of the resources and were skillful enough with the command line, we wouldn't even need HTML. They can just curl in their interactions with those resources :)

index just makes it easier to work with collections. It is still a well defined resource and has a unique representation, for example /books. How it is handled on the server side code does not make it RESTless (I just made that up, but its awesome).

The limits of RESTful architecture

Where I work we have decided to try to be as RESTful as we can, but we are also going to be pragmatic and when something doesn't fit well with REST guidelines (and everyone involved agrees this is the case), then will be willing to diverge. Saying that, I think you can make most use cases somewhat RESTful.

How about something like this if you do not know the user's ID. A collection of change password tokens with the id as the email address:

GET /changepasswordtoken/{userEmail}

Or if the client of the API knows the User ID this would be nicer maybe:

GET /user/{userId}/changepasswordtoken

You are asking to GET the change password token for the user. If this is a public facing API, then obviously you won't return this in the response payload, but the payload could return a message saying "Change Password Sent to Email" or something.

Then to update the password PUT or PATCH the user with the change password token as a querystring parameter.

PUT /user/{userId}?changepasswordtoken=xyz

{
"password": "new password"
}

Rails: RESTful resources: Worth using or inflexible/overrated?

Resources are convenient, but they are not a "one size fits all" feature. Some things just don't make sense with the 7 methods.

Keep in mind that you can:

  • Exclude specific methods with :except.
  • Include only specific methods with :only.
  • Add your own methods to the resource.

So they aren't as inflexible as you may think. But if, after taking those 3 points in mind, the resource just doesn't "feel right", skip it! REST was never meant to replace regular routing, it just tries to abstract away the most common use case.

If you skip out on RESTful resources completely, you'll be missing a ton of free functionality. Use it wisely and you'll be fine.

Proper RESTful routing for rails application?

Unfortunately for someone getting started, there are no laws to provide guidance. You've probably done about as much as you can by reading some recommendations. Personally, if I'm going for restful, I'd avoid sessions as much as possible, and put information in the URLs.

create: Since you are posting the name/email/etc. data, I would post the developer flag also. I'd need to know more about your form to say whether the developer parameter is a good idea; it really doesn't matter much in this case. I'd say if it's a flag in your signup-form view, the parameter is good, and if they are truly different pages, a different base url would make more sense.

regular pages: Your accounts/1/blogs/1/pages/1 is very unambiguous for humans and should be easy on machines as well. Stackoverflow uses a more compact notation, with some redundant information to help out humans and search engines. Use whichever you like better.

How can Rails' REST implementation be said to be REST at all?

What makes a system RESTful or not isn't so much the verb it uses, but the fact the interactions are driven by the hypermedia (in this case, this includes code-on-demand JavaScript).

The GET/PUT/POST/DELETE mapping you're quoting works fine for CRUD operations, but isn't necessarily appropriate for everything (and isn't necessarily supported by all browsers). This is a reasonable rule of thumb to design a RESTful system, but it's neither sufficient nor necessary. (It's in the same category of ideas as what people insist on when they want "RESTful" URIs: there's no such thing.)

Part of this comes under influence of books like RESTful Web Services. It's a good book, but it came out at a time where WS-*/SOAP was predominant, and where everything was tunnelled through POST. A reaction to SOAP was to make people aware that there were other HTTP verbs they could use.

For REST, what really matters in particular is to respect the notions behind the URI concept, the semantics of each HTTP verb (no side-effects, idempotent requests, ..., where appropriate and if you're using HTTP) and the HATEOS principle. It's an architectural style, don't stress too much about what POST/PUT/DELETE the JavaScript does underneath.

You should certainly read these:

  • REST APIs must be hypertext-driven
  • It is okay to use POST

EDIT: (Following comments)

What I should have said was this: If most frameworks turn DELETE
http://server.tld/resource/1 into POST
http://server.tld/resource/1?_method=DELETE, then what's the advantage
of that approach over just using POST
http://server.tld/resource/1?my_method=delete in the first place?

  • It makes the overall goal a little bit cleaner/clearer, in terms of API design. REST frameworks can ultimately only be as RESTful as one uses them, since REST is an architectural style, not a protocol or an implementation.
  • In addition, strictly speaking, the URI includes the query component, so http://server.tld/resource/1 and http://server.tld/resource/1?my_method=DELETE could identify different resources in principle (although that wouldn't be a good design choice).
  • It's good for the framework to be able to expose DELETE/PUT as such directly, but have a fallback solution via POST for the clients that don't support it.

    The reason for this is that clients that do support DELETE/PUT will be able to make use of them, and make assumptions about their usage. It's not so much of a problem for the client to treat a request as non-idempotent even if it was idempotent in principle as the opposite. If the client thinks it can send at most 1 request (non-idempotent) when it could have sent N+1 of the requests, this doesn't cause major problems; if the client thinks it can send N+1 times the same request for something that shouldn't be idempotent, this can cause quite a lot of problems. Emulating PUT through POST is OK, you're just not making the most of PUT, emulating POST through PUT would be problematic.

In making a RESTful api, is there a recommended way to handle route syntax involving multiple queries?

REST doesn't care what spelling conventions you use for your resource identifiers. As long as your spellings are consistent with the production rules described by RFC 3986, you're fine.

If you have a lot of similar resources, it can be convenient to use URI Templates and variable expansion to define your family of identifiers. That allows clients to use general purpose libraries to construct your identifiers, and allows you the option of using a general purpose library to parse information out of the target URI for each request.

Beyond some purely mechanical concerns (ex: using the proper escape sequences), it really doesn't matter whether you use variable expansion in the query, or in path segments, or multiple times in each, or whatever.

There are trade offs to consider -- path segments combine well with relative resolution; application/x-www-form-urlencoded key value pairs combine well with HTML forms.

Beyond that, the machines don't care. So choose any spelling that makes things easier for some people that you care about.

RESTful Authorization

Sorry I don't have time to do this question justice, but it is nice to see some well thought out questions on SO.
Here are some comments:

Don't fall into the trap of mapping the HTTP verbs to CRUD. Yes GET and DELETE map pretty cleanly, but PUT can do Create and Update (but complete replacement only) and POST is a wildcard verb. POST is really to handle everything that does not fit into GET, PUT and
DELETE.

Using attributes to represent an object's status is only one approach to state management. I am guessing you can imagine what the following request might do:

POST /LockedPosts?url=/Post/2010

A subresource is also a valid approach to manage the current state of a resource. I would not feel obliged to treat a resource's "state" attributes and its "data" attributes in a consistent manner.

Attempting to map resources directly to tables is going to seriously constrain you. Don't forget that when you follow the REST constraints you suddenly are very limited in the verbs you have available. You need to be able to make up for that in being creative in the resources that you use. Limiting yourself to one resource equals one table will severely limit the functionality of your end application.

We regularly see Rails, ASP.NET MVC and WCF Rest users posting questions here on StackOverflow about how do certain things within the constraints of REST. The problem is often not a constraint of REST but in the limitations of the framework in its support for RESTful applications. I think it is essential to first find a RESTful solution to a problem and then see if that can be mapped back to your framework of choice.

As far as creating a permissions model that exists at a finer grain than the resource itself. Remember that one of the key REST constrains is hypermedia. Hypermedia can be used for more than just finding related entities, it can also be used to represent valid/permitted state transitions. If you return a representation than contains embedded links, conditionally based on permissions, then you can control what actions can be performed by who. i.e. If a user has permissions to unlock POST 342 then you could return the following link embedded in the representation:

<Link href="/UnlockedPosts?url=/Post/342" method="POST"/>

If they don't have that permission, then don't return the link.

I think one of your difficulties here is that you are trying to chew too big of a problem at once. I think you need to look at the RESTful interface that you are trying to expose to the client as a distinct problem from how you are going to manage the permissions and predicates in order to manage authorization in your domain model.

I realize that I haven't directly answered any of your questions, but hopefully I've provided some viewpoints that may help in some way.



Related Topics



Leave a reply



Submit