I often see weird stuff in Rails applications. One that I always find weird is when people put stuff that belongs to the domain of their application inside the
/lib folder. Let’s talk about why most of the stuff inside lib doesn’t belong there.
Ruby on Rails architecture
First, let’s quickly go over the Rails architecture. I’m sure you know it very well but still, I want to clarify a few points.
/app folder contains all the logic used directly by the application: models, controllers, views, mailers and so on.
/lib folder, as the name implies it, is meant to contain libraries. We both know that in Ruby, libraries are packaged as gems 90% of the time (I love to make up statistics). So what is this folder supposed to be used for then? Well, it’s not complicated. It’s for libraries that are not packaged as gems but could be.
The rest of the folders in a Rails application contain everything that does not belong to the business logic. Database schema and migrations, configuration, tests… The stuff that allows the application to run correctly but not the application itself.
The /app folder
Everything that is directly related to your business logic should be put inside the
/app folder. What if you want to create a PORO (Plain-Old Ruby Object)? Well you can put it in app, it belongs there. You can put it in the
models folder except if you prefer to keep stuff organized. In that case, create a new folder! People do that all the time with
decorators and so on. It’s not because Rails doesn’t have those by default that you cannot create them. Rails is your b**, do whatever you want with it!
What you should put inside this folder:
- Your models, controllers, views and mailers.
- Any other entity you create (class, module) that holds some business logic.
What you should not put inside this folder:
- Configuration, migrations, tests (obviously).
- Generic entities (class or module). For example, a class to perform a bunch of generic calculations on an array (median, etc) should be in
/lib. Why? Because it’s a generic feature that could easily be extracted to an awesome gem usable by other people.
The /lib folder
Now that you know what to put inside the
/app folder, you also know what to put in
/lib. All the generic logic you create to do some calculations, transform images or deal with authorization (don’t re-create though, use CanCanCan).
It doesn’t have to be just ruby classes. It can be models, controllers and views as long as it’s generic enough. Now you can put them inside an engine, give it a cool name, package it as a gem and share it with your friends. Congratz!
Once in a while, you should clean up your
/lib folder. You should be able to extract a bunch of stuff from there and package them as gems. Note that you don’t necessarily have to. I understand that extracting code means another project to maintain and update. It’s a nice way to give back to the community though.
Stop putting stuff in /lib
I wrote this article because way too often, I see stuff inside the
/lib folder that contains important application logic. The default folder structure generated by Rails is great but you can go further! If you need decorators or presenters, just create new folders in the
If you don’t know about it yet, there is a cool thing named DCI that suggests using services to implement the interactions between objects. Take a look!
Everything in this post is just my opinion, if you think it’s a bunch of ‘bs’, you can tell me what you think in the comments. I think it’s all about style and if you’re happy with the way you organize your code, good for you!
Just don’t spit on people who like to do it in a different way ;)