RESTful design, how to name pages outside CRUD et al? - ruby-on-rails

I'm working on a site that has quite a few pages that fall outside my limited understanding of RESTful design, which is essentially:
Create, Read, Update, Delete, Show, List
Here's the question: what is a good system for labeling actions/routes when a page doesn't neatly fall into CRUD/show/list? Some of my pages have info about multiple tables at once. I am building a site that gives some customers a 'home base' after they log on. It does NOT give them any information about themselves so it shouldn't be, for example, /customers/show/1. It does have information about companies, but there are other pages on the site that do that differently. What do you do when you have these situations? This 'home-base' is shown to customers and it mainly has info about companies (but not uniquely so).
Second case: I have a table called 'Matchings' in between customers and companies. These matchings are accessed in completely different ways on different parts of the site (different layouts, different CSS sheets, different types of users accessing them, etc. They can't ALL be matchings/show. What's the best way to label the others?
Thanks very much. =)

I'm certainly no expert, but if you rethink your resources and think of them more strictly as 'nouns' or at least lists of data, it might be easier to fit any desired action into GET, POST, PUT, and DELETE. For example, you have a /customers/ resource could presumable have a /customers/{username}/ resource for each customer. Maybe that gives them information about themselves. You could have /homebases/{username}/ or /customers/{username}/homebase/ as your homebase resources. Presumably, you'd access that homebase resource mainly through GET, and POST if there's anything there to update (which I wouldn't expect on a home-base or dashboard since it's an aggregate resource).
For 'matchings' you could use something like /matchings/{customer},{company}/ (yes, commas and semicolons are allowed. Commas usually mean the two parts are order-dependent and semicolon means order-independent, though there's no rules about it). From that resource, you can have GET to read, show, and list whatever data you need (including optional query parameters passed as the body of the GET request), POST to update, PUT to create, and DELETE to delete. Using the parameters passed in GET, you could also request different views of the same data. Of course, you can have sub-resources of that matching like /matchings/{customer},{company}/invoices/{invoice#}/.
I liked the book "RESTful Web Services" (2007 O'Reilly), by the way.
I hope that makes some sense and is helpful. =)

Aggregate and composite views are a serious problem, I think. I had to deal with the homepage problem that went against everything RESTful I knew.
My solution was to consider the homepage or dashboard as a resource in itself, but a resource where only GET operations made sense. POST/PUT/DELETE from the homepage were directed to the specific resources as usual.
Matchings, in contrast, seems an easier problem to tame. It seems like a simple mapping between Customers and Companies from your description, and you could parametrize it based on querystring parameters.
/matchings?companies=X,Y,Z&locations=NY,CA,TX

By RESTful design, I assume you mean RESTful web services, since a REST-based architecture has a much broader sense than that.
The main thing to consider is that REST-based architectures rely on the HTTP protocol, in virtually all cases. Since HTTP specifies a set of methods, sometimes these methods are used to create the so called RESTful web services.
But the RESTful web services don't follow any concrete standard (unlike SOAP). It is common to use:
GET - for fetching existent items
POST - for creating new items
PUT - for updating existent items
DELETE - for removing existent items
Create, Read, Update and Delete (CRUD) are the basic functions of any persistent storage.
It is easy to see that in common RESTful web services, each HTTP method is being used to match one of the basic functions, but the point is: it doesn't have to be this way.
There are other things to consider, URL mapping is one of them (as this is the concern of your question), security is another. POST requests send the content of the request in the HTTP body (which can be encrypted), but GET requests send it in the URL, visible for everyone to see.
If one wants to develop a secure (encrypted) RESTful web service, one could make all requests HTTPS POST, and then specify within the request, which of the CRUD operations one wants to perform, and on what resources.
One could also expand the CRUD concept to a wider range, in fact, in almost every application, one has to.
Remember CRUD are just the four basic operations in which all other actions can build upon. There's no standard you have to follow, you can specify your own protocol, according to what makes sense in your context, and keeping all the relevant considerations in mind (security, URLs, etc.)
Specifically regarding your question, you can have your own actions, like show_by_x, show_by_y, etc. The REST police is not coming to arrest you :-)

REST and ORM is 2 different things, because of that even though you have a model called User , you done necessary to have a users resource. Resources should be managed in the rails controller level
Think resources as modules/sections
Ex: you might want your users to land on a dashboard page after they log in (and say you have two categories of users Administrators and normal users), so you can have two resources namly
admin_dashboard
uer_dashboard
and both might only have read action
Second case :
consider having something like above example (different resources according to different user levels) if possible
I'm not a REST guru, but hope this helps :D
cheers,
sameera

Related

Rails: Handling permissions for individual tables and composite views concisely

I'm struggling to find/understand the Rails concept for handling table permissions and permissions for composite views (and composite updates).
Logically, Create, Read, Update and Destroy permissions for tables should be at table (model) level. If I know exactly which permissions a user has on a table, then it is possible to derive from that whether the user has the necessary permissions for any particular view (which just consists of data from one or more tables), and I should never have to repeat these permissions.
The 'Rails Way' would therefore seem to demand a controller for every table (model) that will be used by the application, in order to set permissions for that table in a precise way (using before_action or whatever to validate the user for the particular CRUD action). (Aside: I'm not even sure if there's a good reason for not moving the permissions logic into the model itself, which is actually what I did initially before trying to adhere to convention a little more.)
However, Rails (and possibly MVC in general?) seems to dictate that there should only be one action/view per request. So if I want to make a view consisting of three 'index' views, one for each of the models A, B and C, I need another action/view and a new validation rule for this action. This new validation rule, of course, shouldn't be necessary; the user is allowed to see this new composite view if they're allowed to see each of the individual 'index' views (or more precisely, the data underlying these views).
Also, any Create/Update/Destroy params received relating to a specific model should ideally be passed to that model's controllers for validation/execution (and there may be parameters for instances of multiple different models). I don't think this is typically how it is done, however, because it would require multiple actions being called.
Have I misunderstood the Rails methodology for handling this, or is it really expected that you effectively repeat yourself with regards to Create, Read, Update and Destroy permissions for composite views (and composite updates)?
First off the Rails framework does not ship with any provisions for authentication (well except has_secure_password) or authorization (permissions) and is totally unopinionated on the matter.
There is no "Rails way" to handle authentication or authorization.
What Rails is geared towards is the Rails flavor of REST which is focused on exposing resources through a structured API. Each controller handles a specific resource or just a specific representation of a resource.
Note that a resource is not equal to a table. Tables are an implementation detail while resources are the abstractions that your application provides as a public API.
Of course since the framework is not opinionated towards any form of authorization you can roll your own in any fashion you want such as RBAC, ABAC etc.
Of course there are several community gems such Pundit and CanCanCan that remove the need to reinvent the wheel.
(Aside: I'm not even sure if there's a good reason for not moving the
permissions logic into the model itself, which is actually what I did
initially before trying to adhere to convention a little more.)
There is a very simple reason why this is a bad idea. Models are not request aware and do not have the proper context for authorization.
A much better alternative is to use a component like Pundit that compliments the traditional MVC structure, but is its own separate entity - you could even call it MVCP.

RESTful websites vs. RESTful APIs - What's the difference and does it matter?

I've been reading a lot about REST and how to do REST the "right way". Most resources use terms like RESTful web services or RESTful APIs, however none mention RESTful websites. I am confused by this given that I think of a website and an API as two different things. Yet, when, for example, designing a website using the Rails framework, you're constantly reminded about how RESTful everything is (or is supposed to be).
I get the fact that REST provides a lot of advantages (its architectural properties) for APIs (e.g. a JSON API), but I just don't see how a website benefits from being RESTful. As a simple example consider login functionality. In a REST fashion this can be modeled by making a Session model with logging in corresponding to creating a new sesssion, logging out destroying a session and so on. The URLs would look something like this:
Prefix Verb URI Pattern Controller#Action
new_user_session GET /users/login(.:format) sessions#new
user_session POST /users/login(.:format) sessions#create
destroy_user_session DELETE /users/sign_out(.:format) sessions#destroy
However, these URLs are not very user friendly. From a users point of view it makes more sense to just have a /login path where the login form is displayed. It is also easier to remember. But if we make the URLs map like that they're not really (as) RESTful anymore; does /login identify a resource. If so which one?
Another example is the home page /home or just /. How does that fit into REST? On most websites the home page is a mashup of many different kinds of information and doesn't identify any single resource. For example it could be a page that lists the newest products in a catalog and the last date you logged in; two completely unrelated things. How is that RESTful?
I understand why having a RESTful API separate from a website makes sense, but my confusion lies with how REST applies to websites - if it even does.
The short answer is that no one talks about RESTful websites because websites are RESTful by default. You really have to try to make a non-RESTful website (though it has been done--see below).
The setup you're describing takes a lot of elements from REST, but it's not "REST" per se: it's a set of conventions designed for the convenience of server-side programmers. Most of today's web APIs only use a subset of the REST constraints, and it's a subset that doesn't include the main driving principle behind websites.
Let me back up a bit. Here's what websites and web APIs have in common: they both expose functionality through resources. Each resource is identified by a URL, and each responds to an appropriate subset of the standard HTTP methods. (This may seem obvious, but look at XML-RPC or SOAP, where there's only one URL for the whole system.) A resource might send documents to the client (in response to a GET request) and/or it might accept documents from the client (along with a POST or PUT request).
Now, the differences. Web APIs often map the four most common HTTP methods (POST, GET, PUT, DELETE) onto the four CRUD operations (Create, Read, Update, Delete). Web sites can't do this, because web sites run on HTML, and HTML forms only support two methods: GET and POST. And yet, a web site can easily describe all sorts of actions--"search", "next page", "purchase", "unfriend"--which are nontrivial to map onto CRUD.
That's because HTML supports links and forms. This is what's missing from the "Web API" branch of the family tree. Not the resources, but the machine-readable connections between resources. (To drop some REST jargon, this is "the hypermedia constraint" or "hypermedia as the engine of application state.")
"Web APIs" tend to ignore the hypermedia constraint because a) it's difficult to understand, and b) JSON doesn't support links or forms, so it's difficult to obey the hypermedia constraint even if you want to. (This is changing with the development of formats like JSON-LD, Hydra, and HAL.)
But the hypermedia constraint is literally what holds the Web together. Take away the links and the forms, and you'd be left with an unusable mess.
Python Challenge is a good example of a non-RESTful website. You get a starting URL and then you have to solve a little puzzle to figure out how to get to the next URL in the sequence. You still have resources, and each resource has a URL. But the connections between resources are obscured. This is fun as a game, but no one would run a serious website this way. Unfortunately, this is kind of where we are in terms of "Web APIs."
Further reading
As you can tell, this is a complex topic. At the risk of tooting my own horn, the "maturity model" I developed for a 2008 talk might help you understand the architectural difference between the World Wide Web (level 3) and most of today's APIs (level 2). I'd also recommend Steve Klabnik's Designing Hypermedia APIs, and my own RESTful Web APIs, which starts out by comparing a web API to a website that does exactly the same thing.
My earlier book, RESTful Web Services, also covers this topic, and it's free to read online. However, it's somewhat out of date (it was published in 2007), and in retrospect I don't think it pushes the hypermedia angle hard enough.
Miscellaneous
To briefly respond to a couple of minor points from your original question:
There is no technical difference between a web API and a website. A website is a web API that happens to serve HTML documents.
One URL is not more "RESTful" than another. This is solely a usability issue. On a technical level it doesn't matter at all what your URLs look like. /users/login.json and /login and /the-first-100-prime-numbers.gif are all equally RESTful ways to refer to a login form.
The home page is a resource: it's a "home page" resource. Its job is to contain the most important bits of information, and to guide the client to other pages--either directly through links, or indirectly through a search form. A resource does not necessarily correspond to a row in a database or an object in an object model. A resource can be absolutely anything, even a real-world object or an abstract concept. The only restriction is that a resource must have a URL.
/login is a URL, so yes, it identifies a resource. What kind of resource? If it's a typical scenario where sending "GET /login" gets you an HTML page with a login form, then it's a "login form" resource. If filling out the login form triggers a "POST /login" request, then it also acts a "login form processor" resource.
You might have better luck thinking of a resource in terms of the code that runs when a request for its URL comes in, rather than trying to map it to one particular "thing" in your dataset. That is, instead of trying to figure out what a resource is, think of it in terms of what it does.
Hope this helps.

Understanding REST conceptually with Rails

I'm a little late to the party, but I'm trying to wrap my brain around how REST is supposed to work, both in general and in Ruby on Rails. I've read a bunch of articles online about this already, but still don't feel like I'm getting the big picture.
REST as I understand it, is a series of aspirational statements, with the net result at the bottom being that URLs should contain all the information necessary to handle a request, and gets should not be able to change the state on the server, and a bunch of other concrete guidelines.
As I understand it, REST in Rails is based around CRUD, which is to say, every model has a create, read, update and a delete action. Each of these actions is accessed through a similar set of URLs, generated by mapping a resource in the routes. So a login URL is creating a user session, so the URL would look like example.com/session/new with a POST, and logout would be example.com/session/destroy with a POST.
What exactly is the benefit of standardizing URLs in this fashion? It strikes me as optimizing for machine readability at the expense of human readability. I know that you could then remap in the routes file example.com/login to example.com/session/new but that is just one more step for no apparent gain to me.
Is it considered really bad practice to develop a website that uses traditional routes now?
Furthermore, each of these CRUD actions should be able to respond to requests with whatever type of response the request is looking for. So the same link to, say, example.com/tasks could also be called at example.com/tasks.xml to get an xml representation of the result, or example.com/tasks.json for a json representation.
Is this to say that a RESTful API would just be the usual links on the site but with xml appended? It strikes me as very strange and awkward that a web API would behave in this way, but this seems to be what's implied by everything I've read. I'm more used to seeing an API that has links like example.com/api/tasks to get the list of tasks. What exactly is the advantage of this approach?
Rest provides another chunk of "convention over configuration." For a widely used, limited set of common problems (crud actions against the models as a whole), rest is very useful as an application development convention.
What exactly is the benefit of
standardizing URLs in this fashion?
Programmer efficiency. Less to think about; enables more time to be spent on harder problems, etc. Better maintainability. Easier testing. Etc.
Is it considered really bad practice
to develop a website that uses
traditional routes now?
Yes, for crud actions that are interacting with an entire record of the model.
Furthermore, each of these CRUD
actions should be able to respond to
requests with whatever type of
response the request is looking for.
So the same link to, say,
example.com/tasks could also be called
at example.com/tasks.xml to get an xml
representation of the result, or
example.com/tasks.json for a json
representation.
Is this to say that a RESTful API
would just be the usual links on the
site but with xml appended?
Yes, if your api fits the rest model. I think the big issue is authentication. If you want your api to be stateless, then you'll probably need to include authentication with each call. At that point, if you don't want to use HTTP level authentication, you'd need to decide how to include the credentials.

Rails: How do I keep a complex app RESTful?

I always try to make my applications as RESTful as possible but I've recently begun working on a complex project that requires multiple additional methods in my controller.
I normally achieve this by adding another :collection to the route but it seems like a workaround and in on scenario I have 5.
Are there any best practices for handling the extra methods in a controller? They are generally simple forms that updates a model.
The other solution, which is what I do, is every time you find yourself creating an action that doesn't fit into the RESTful actions, eg Search, so you might find yourself making a search action on an Article controller, what you could do instead of creating this action is create a Search controller instead, and use RESTful actions inside of that instead. There is no rule saying you need to use all the actions, you might only need one or two, but it keeps your API RESTful and your code organised.
This is not a hard and fast rule, but I have certainly found it helpful when I try to decide where to put stuff.
I think there's a bit of confusion in the Rails community about how and where to use the word "RESTful". Strictly speaking, the only thing that can be RESTful is your web API (as railsninja already mentioned). That the code of an application that conforms to the REST conventions (the application with REST API) can usually be organized into a set of controllers (that match the resources) and methods in these controllers (that match the four verbs of the HTTP protocol) is nothing but a hint of how to keep your application clean and organized.
If we want to talk about a RESTful Rails application, we can't just talk about RESTful controllers - there's nothing RESTful about just controllers themselves. It's possible to have a complex web application with only one controller (and myriad of methods) that represents many resources and is perfectly RESTful.
That said, it's pretty OK to add more methods to your controller. Sometimes, it's good to extract some of these extra methods and create a completely new controller - make this any time you feel good about it (rule of a thumb: create new controller anytime you are able to identify it with some self-sufficient resource, ie. a resource which could exist just by itself). Sometimes though, it'd be silly to extract some resource to a different controller. Say you have a resource which has a status attribute. It makes sense to perceive this status attribute as a resource by itself and perform at least one action on it (update), but it won't make any good to extract it to a different controller.
There is a Railscast about this topic, adding custom actions to an otherwise RESTful controller.
Edit: I see that you've mentioned the method in the Railscast as a workaround already. :-) I believe the only other "pure" way to handle it would be to add additional controllers as required to support the actions you want.
"I normally achieve this by adding another :collection to the route but it seems like a workaround and in on scenario I have 5. "
This sounds perfectly fine to me. REST is not about the crud operations and your concern seems to stem from the fact that you are doing more than the basic crud operations but there's nothing wrong with that.

How do I know when to and whether to have a separate controller for a piece of code?

So I am in a situation where I have to decide whether or not to have a separate controller for a particular piece of code. We have a home page that acts like a hub for the rest of the site. The page is accessible to all users (logged in as well as non-logged-in). I was thinking about having home as a separate controller and an action called index. Thinking about this situation, I started wondering if there are any rules or guidelines on this front.
My perception has been that if a code revolves around an entity, separation is needed. (Similar to REST guidelines) If the entity is a noun, it should be a controller. If the entity is a verb, it should probably be an action and should reside in the controller whose name is the same as that of the noun that the verb refers to. Some colleagues suggested that since this is one action, it should reside in the some existing controller and should be named home. I strongly disagreed, however, I could not find a trusted source that would back me up on this.
Would like to know your thoughts.
In this case I have to agree with your co-workers.
REST is a nice approach to take when dealing with resources, as you say. This allows you to create a consistent interface especially with a view to creating a web service.
However REST doesn't actually map too well to a web browser setting. You'll notice for example that even for resources your /edit and /new actions are just GET requests returning an HTML form pointing to the relevant RESTful action. 'edit' and 'new' aren't RESTy at all.
Similarly, the home page is generally a user-friendly amalgamation of various data, not suited to a RESTful interface. So either just stick an extra controller in with one action, or alternatively use an existing controller's 'list' action as the home page
The problem starts with the phrase
If an entity is a verb
If you are attempting to produce a RESTful architecture, an entity cannot be a verb. The only verbs allowed if you are using HTTP are GET, PUT, POST, DELETE, HEAD, OPTIONS. All entities should be mapped to some noun and if you are trying to retrieve that entity you should be using the verb GET. Personally, I would map that to the method Get() on my controller but I don't know if Rails lets you do that.
The quick (and unhelpful) answer is that either way works fine.
I think that everybody comes across this decision at one point, and the decision you make depends on the likely future of the website... which means it's prone to premature optimisation... but that's always the catch,
As you've probably guessed by now, "home" is in some ways a verb as well as a noun, thus why you're having trouble figuring out what to do.
The answer depends on a combination of interpretation of your website structure and how much time is available to you...
if you have very little time to work on this... then stuffing the 'home' action into another controller is often considered the expedient option. It works, it lets you move onto other (probably more productive) tasks.
However, I agree that sometimes it is good to step back and think about what you're doing and whether it could be done "better"...
in this case, though it's harder to define "better" - as it's unlikely that putting the home action in a new controller would be measurably faster... and if it's the only action int he controller... it's debatable whether it's better, architecturally, to just adding it onto an existing controller...
So we start in on what is mostly a philosophical debate... in other words, no answer will be "more correct" than the other- it's more a matter of taste and circumstance. In this case, the debate hinges on making the structure more RESTful.
To be faithful to RESTful architecture, you would indeed move the action into it's own controller... but you'd first have to identify what the entity is. The "home" page is often not readily identifiable as a specific db entity... it's more often a portal-page.
Sometimes you can pick an entity eg online shops will often have a home page that is actually a "products#index" variation, or sometimes the "home" page is a UserAccount#show page... but more often, your home page will not be simple, and will combine information from multiple entities... thus why it is difficult to decide what the "right" architecture will be.
If you cannot identify a specific entity, then there is a valid debate as to whether to move the action into a specific controller.
however, you can always create a new "entity" that is centred around the architecture of the site. This is especially likely if you are going to come up with other non-entity-specific pages for the site (eg T&Cs or an "about our company" page).
The usual fallback being a "PageController" (or similar name) which isn't linked to an Active Record model, but to a more nebulous entity, in this case a "page" which is recognisable to a user of the website (eg the "home page" and the "T&C page" and the "about page"). Each action would be for a specific page...
So, it's up to you as to whether this fits better with your view of the architecture of your system... and whether it's worth the effort... but that's my view on the debate. :)

Resources