Architectural best practices - where to put non-REST actions? - ruby-on-rails

I'm making my first real Rails app, and am learning about REST architecture and how it fits into Rails apps. My controllers don't really seem to map logically to an individual resource, so it's tough for me to implement strict REST. For instance, I have a "catalog", "checkout" and "admin" controller, not a "products", "categories", "orders" and "users" controller, although those are the main resources being used in those controllers. Each of the controllers does more than just REST actions on a resource however, all of them pull from multiple models and service multiple views.
Am I missing a design/architectural practice that would make REST work better here? Namespaced controllers perhaps, with non-REST actions in the top-level controller only, and REST actions in the sub-controllers? Seems like I would run into some DRY violations there...

If this is the way you want to structure your app, forget about REST and just map the routes you need. If you don't actually want to manage resources why bother?

REST is great for resources. It's really painful to map a checkout procedure as a restful resource and not worth the effort, personally, I just have 4/5 actions in my checkout controller and that seems to do the job.
If you want the helpers, you can map named routes
checkout_delivery_path
map.checkout_delivery '/checkout/delivery', :controller => "checkout", :action => "delivery"

If you look at the HTTP spec here
you will see that one thing that POST can be used for is:
Providing a block of data, such as the result of submitting a
form, to a data-handling process;
So, you can create a controller that is a "data-handling process" and do a POST to it without violating any REST constraints. If you name the resource with a noun you can make URL feel a bit more RESTful, but it really is not not necessary. e.g.
POST /MyStore/CheckoutGirl
As for your Catalog, I don't see why that doesn't map easily.
GET /MyStore/Catalog/Item/2324
GET /MyStore/Catalog/SaleItems
The admin usually maps to users, roles, etc. There is nothing new there.

Stop trying to shoehorn every aspect of REST into every application. REST is an architecture, and it's not suitable for all purposes. If what you need is some RPC action, then use some other form of RPC, not the resource-centric principles of REST.
Also, the URL naming schemes are totally irrelevant to whether your application is RESTful or not. That's not what REST is about. They're nice to have, but just do what makes sense for your application.

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 design, how to name pages outside CRUD et al?

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

Should rails ajax calls be bundled into their own separate controller?

Should AJAX calls that are not RESTful be:
put in the controller that most suits their functionality/view, or
bundled together into their own separate 'Ajax' controller?
I've been doing 1, but I've just read this (2725 diggs) article
http://zygote.egg-co.com/10-dirty-little-web-development-tricks/ (see point 9)
and this chap opts for method 2. But he is a PHP developer though.
One benefit could be that 2 might clean up the routes by doing something like 'ajax/:action' instead of adding members to restful routes.
It seems like a 6.5 of one, half a baker's dozen of the other type thing.
Which option do you go for?
I prefer the first approach:
it's semantically consistent. if an Ajax action involves resource XXX, you (and other coders) will know where to find things in your application, thanks to Rails conventions.
if your application is heavy on Ajax (and nowadays most of them are), you will end up with a behemoth AjaxController that negates the whole RESTful thing. The rest of your controllers will be there just to provide gracefully degraded non-javascript CRUD actions.
Similarly, testing your Ajax controller will tend to be somewhat messy because you will have to set up scenarios --load fixtures, mocks, etc. for each and every "ajaxified" resource of your app.
Your "RESTful" controllers probably include new and edit actions, neither of which are actually RESTful, they just provide user interfaces for the create and update REST actions. new and edit don't get a separate NonRestUIController or something, they are kept in their associated resource's controller, keeping your controllers semantically consistent. Similarly, Ajax actions that relate to a certain set of functionality or a certain resource should stay in the associated controller.

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