Vít Meloun

Posted on 22nd July 2019

Rails PRO tips: #1 The Rails Way

news-paper News | Software Development |

Hello, I am Vítek, and I’ve been programming in Rails for 6 years. In this series of articles, I would like to share some interesting and important stuff I wish I understood at the beginning of my Rails path, so I didn’t have to learn it the hard way.

road in the desert

We will go through a list of practices that made my Rails programmer career easier in the long term and that are definitely worth checking. You can agree with me, you don’t have to (and it’s fine), but you should be aware that those topics exist.

My articles won’t give you an absolute answer to the question “What are the general rules I must always follow to become the best programmer in the world?”. And they aren’t supposed to give you one – in one of the articles to come, I will try to explain why the question itself doesn’t really make sense to me.

Well, that’s it for introduction; let’s begin with the main (and surprisingly, even in the year 2019 still a little bit controversial in the Rails community) topic.

The Rails Way, or: Don’t let your business logic dissolve in Rails

When you begin with the Rails framework, very soon you will spot the path you are supposed to follow: the application has models, views and controllers, and your code should fit somewhere into that structure. If you try a “Getting started with Rails” guide, there is a pretty decent chance you will end up with a TODO list, having its high-level logic (like “what is a TODO task”, “how to complete it”, “how to order the list”) defined in a file the framework has generated for you.

This is not necessarily bad – small applications can be fine with this MVC approach. But when your app grows, you will see that it has limitations and problems arise: core logic begins to be spread across multiple not-really-related places, every time harder to find. The app will have slow tests and very big models, being almost impossible to reason about (or even read). And every change becomes harder and harder, introducing bugs in places you didn’t even know were there.

The beautiful little app you loved and enjoyed improving by adding new features becomes a nightmare (or hell, if you’ve tried to “solve” the situation by concerns), that will make you hate your life and question every freaking choice you made. Trust me; we have all been there.

Who to blame?

Now, what exactly went wrong? Someone could say the MVC is to blame here, but I can’t fully agree with that. MVC itself is a good concept; the problem is it’s intended for something different than what Rails uses it for (it was a pattern to create GUI on computers from the 1970s).

And even if MVC was a great fit for web development, it would change nothing about the real issue we are facing here. The thing is, what you do by following the “Rails way” is you are melting your business logic into a tool that is supposed to take care of displaying a web page to a browser or save a database row.

What you want to achieve instead is having all your precious business logic separated from Rails specific places like models or controllers – or views, oh-my-god – into small, simple, independent, easily-testable, framework-agnostic Plain Old Ruby Objects (POROs).

Realize what is important and what is not

When you decide to develop a brand new e-shop system, begin with a small, simple object for your order (that inherits from nothing; just a PORO). Design an interface to make it communicate with products, a product being another PORO. Decide what the API of delivery types and payment gateways should look like.

And keep going like that, using only Ruby, until you end up with all the domain logic designed, polished and ready to be used. After that, you can easily connect this independent ecosystem of yours with a Rails skeleton.

Oh, I hear you. But you need The Mighty Active Record during the process, don’t you?

No, you don’t. Not yet.

For working with persistence at this early stage, just use a file for that. Or cache. Or Google Spreadsheet. Who cares; just inject something that can deal with that into your POROs. Design your system and its abstractions so you don’t have to think about some low-level stuff (like the database) when you create the high-level concept of your app.

Also, notice you don’t need to spin up a webserver to work with your order or product. You can add it later. Your order doesn’t know the way it will be displayed to a user, and that is exactly the goal you want to achieve. Imagine how fast your tests will become when you don’t need a running webserver and database for most of the time.

Framework is irrelevant

So, the important take-away for you is: make all those design decisions that really matter first; create your core business logic independent of the rest of the world, and after that, you can just plug the result into a framework. It may be Rails. It may not. The point is, it is not that important.

What I want you to understand is, compared to your business logic, any framework should be just an unimportant, not really relevant, delivery mechanism.

If you are interested in this topic, you should definitely check out Uncle Bob Martin’s videos and books. On YouTube, there is a lot of his talks that made me understand this topic a while ago.