After some discussions with our Rails developers team, we agree on some guidelines for our controllers. You should understand why controllers should stay skinny and there are some tips you can use to reduce their size. Controllers are the user flow and they handle inputs and outputs from/to the final user. They don’t need to know too much about your app.
What a controller should do
Validate inputs: params from the URL, the body, and the query string must be checked in controllers. with .permit and routes constraints in Rails 4 (for example)
Check authentication / authorizations. Is there a current_user? What can he access?
Deal with cookies and sessions: You will get or set values in cookies in your controllers and use the session when needed. It’s prohibited to use sessions in models and views. Views can eventually read from the session or from a cookie (not write).
Detect what format to output: Depending on the request, you will output JSON, HTML or whatever format the user need. This is a controller responsibility.
Set correct HTTP headers: I encourage you to try Varnish or a similar reverse-proxy (like rack-cache if you want to use it on Heroku). It’s your controller job to correctly send the HTTP expires headers.
Respond with the right HTTP status code: This is transparent for a lot of apps with HTML only navigation. But you need to properly set HTTP status code in your responses.
Fetch the right data: You will ask a model or some models for data that will be passed to the view. Just query a method on a model with the right parameters. That’s it: no complex SQL queries, low-level caching stuff and no complex data manipulation in general (this is for your models).
Use application_controller to factorise some behaviors but don’t make it fat. Use helpers if it’s for views only.
What a controller should not do
Make raw SQL queries or complex data structure.
Call external API services (HTTP requests or what ever).
Fetch data from multiple models: Try to limit the number and kind of models you call in an action. Create another class if you need to manipulate multiple models.
Do core data manipulation or domain logic: try to think outside your controllers. Their are here to handle your client i/o. That’s the only purpose. All the rest of the database and core domain are independent.
Know too much about your app, the database and caching stuff: The configuration for databases, caching and others things are done in config/.
It’s a very quick note and it needs more examples and details. But you have the big picture. Please don’t blame frameworks to “encourage FAT controller”. It’s your responsibility to understand the purpose of controllers.