Skip to content

Instantly share code, notes, and snippets.

@Dacello
Created September 22, 2014 19:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Dacello/9916f3e5822d7dda1a7f to your computer and use it in GitHub Desktop.
Save Dacello/9916f3e5822d7dda1a7f to your computer and use it in GitHub Desktop.
#Skinny Everything (1 of 3)
At Revelry, we build web apps using Rails. Working with Rails, or any MVC/MVP framework for that matter, you always come across the saying "Fat model, Skinny Controller". The idea is to slim the the controller down to basic CRUD actions, and put the rest of the more complex functionality in the model. It definitely is good to have a slim controller for sake of code reusability, readability, and testing. However, it is also good to have a skinny model. For the exact same reasons. In fact its good to have a skinny everything.
What tends to happen when you move all logic into models is that you get "God like Models" which [become impossible to understand and maintain](http://stackoverflow.com/questions/14044681/fat-models-and-skinny-controllers-sounds-like-creating-god-models). Jon Cairns wrote a great article about why ["Fat model, Skinny Controller is a load of rubbish"](http://blog.joncairns.com/2013/04/fat-model-skinny-controller-is-a-load-of-rubbish/). Cairns says:
```
No class should be fat. Ever. There is no need for your controllers, models or views to be fat; this shows laziness, as there's been no thought given to the application's design outside of deciding to use a particular framework.
```
Unfortunately, Cairns doesn't list any of the ways to keep everything skinny.
So, I have decided to write a two part article of articles covering different tactics for having "Skinny Everything" in Rails
##1. Decorators
Sometimes you need a way to implement display logic on an object. For example, you want @event.start_date to be a correctly formatted date. You might think it would make sense to just add a method to the model:
def formatted_start_date
start_date.strftime("%A, %B %e")
end
That seems like a good idea, because then you will be able to call @event.formatted_start_date everywhere that you have an Event object. However, according to MVP, the model isn't supposed to deal with presentation; that's meant to happen primarily in the controller. Not to mention, display methods like this can add up, leading to fat models. This may lead you to consider writing a helper method that formats the date for you. That is probably a bad idea. If you don't know why, here's an article about why [Rails helpers are shit](http://nicksda.apotomo.de/2011/10/rails-misapprehensions-helpers-are-shit/).
Instead, the a good option is to use a decorator. At Revelry [Draper](https://github.com/drapergem/draper) for decorators.
Here's an example of solving the above issue with a with Draper decorator:
```
app/decorators/event_decorator.rb
class EventDecorator < Draper::Decorator
delegate_all
def start_date
object.start_date.strftime("%A, %B %e")
end
end
```
Then in the controller, you decorate the @event object with EventDecorator.decorate(@event), which returns the decorated @event object. So know you have the start_date method. One thing to remember is that you need to decorate the event object in order to get that method. If it was just in the model, you could call it on all event objects, but with a decorator, you can only call it on a decorated event object.
The next part to this article will cover Concerns, another great way to skinny down both controllers and models alike.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment