I was taking a looking at the Upcase repository on GitHub and wondered what is your take on Rails directory structure. In particular, in relation to Upcase, I wanted to know:
What code do you usually put in your app/services ?
What code do you usually put in your /lib ?
What code do you usually put in your app/models ?
I am currently having a discussion on the topic with my team and I wanted to know what is your take. I am not looking for the “correct” way, I am mostly interesting in knowing what are the reasons driving your directory structure (i.e. why you put a class in a specific folder) and whether you have had experiences with other folder structures and what where your take aways.
My initial curiosity was around Upcase but I am interested in knowing about other experiences (i.e. by non thoughtbotters) as well.
This is a topic of considerable debate and discussion amongst Rails developers! Here’s my strategy for organizing code:
I only put code in lib if it’s truly uncoupled to the application’s domain, and I’m preparing (as in, making the final changes needed) to extract it out to a gem. I almost never have anything in lib as a consequence.
Anything that represents a domain concept goes in app/models. These don’t have to be ActiveRecord models. They could be null objects (MissingSubscription, GuestUser) or models that represent a concept that’s not backed by the database.
app/services would be for objects that perform tasks for the system that aren’t domain concepts. SubscriptionImporter, WeatherDataUpdater, etc. would be the kinds of classes that aren’t domain models.
Keeping code in app over lib works for me because when I want to search code and limit the search to application code without specs, I can limit the search to app without needing to worry about including lib (or worse, forgetting to include it).
In general, I wouldn’t be afraid to do what feels comfortable to you here. There’s not that much in the way of negative consequences to using app/models as a “junk drawer” of code that doesn’t fit in a controller or mailer. On an application I built, after two years we had:
app/controllers
app/decorators
app/helpers
app/mailers
app/models
app/policies
app/serializers
app/services
app/validators
app/workers
plus a few more very domain-specific folders.
This is only somewhat related, but I cannot recommend enough Bryan Helmkamp’s blog post 7 Patterns to Refactor ActiveRecord Models as a great read an an inspiration for how to organize your Rails app.
thanks for the reply. I think I somehow share the same opinion with you regarding the folder structure.
The only part I’m somehow still not sure is the app/services folder. From what I could understand, what would eventually go into that folder are kind of domain concepts (or deal with domain concepts), but often represent processes rather than things. Have you ever pondered such an argument? And if yes, what makes you still consider that folder as a valuable presence.
Things in services could certainly be considered “processes” from a functional standpoint. Often things in services are items that could later end up being most of the guts of a background job (or just called by a background job that wraps it).
@ghanima do you have access to the Upcase repository on Github with your Upcase plan? Under app there are folders there for services, which is the most significant breakout of classes from using app/models as the “junk drawer” for everything.