Improving Your Rails Codebase

Source: Giphy Dot Com

Yes, Rails scaffolding is one of the big benefits of the framework. You, however, soon get to a point where it’s obvious that certain things are not a good fit for any of the three directories representing the MVC in your codebase. There are many ways (patterns) to address this, we’ll touch on a few.

Let’s take the example of a Fintech company enabling registered users to complete the KYC process by setting up their own profiles, and then doing some verification of the submitted information.

Some assumptions:

  • The data required for KYC include a photo, proof of address, bank account, and NIN (National Identification Number).

Firstly, completing the KYC setup is not critical to the use of the app because all users can carry out transactions less than the set limit, regardless of their KYC status. Hence, making the KYC set up optional during user registration seems like a great decision in terms of user experience and reducing bounce rate.

Secondly, while setting up the KYC profile, users don’t want to wait until you’ve verified their information before they can successfully make a submission. If you need more information on the submitted KYC data you may notify the user later.

Let’s get a bit technical. Just a bit.

You probably need some:

  • model to represent the KYC entity.

Asides from the above, you want another process that is responsible for how you handle the submitted data. You might want to:

  • Store the photo in a 3rd party service e.g S3, Filestack, Cloudinary, etc.

To carry out the above, you definitely don’t want to have the logic in your MVC designated folders. Since this should be handled by a different process, it might be a good time to think of background workers. Uhm, but you don’t want to make an upload or call verification APIs directly in a worker, maybe create a service object to do this, then call that object from the worker? That would make your code organization neater, and testing your code easier. Sounds like a plan!

Service objects? Yeah, service objects are SOLID compliant POROs (Plain Old Ruby Objects). A service object does one thing in your domain logic and does it well.

Where should you keep your service objects? You can create a directory for them within the ‘app’ directory of your project. Having it there would be great for autoloading constants from your POROs.

# app/workers/address_verification_worker.rbclass AddressVerificationWorker
# app/services/address_verification_service.rbclass AddressVerificationService

Some folks prefer domain objects to service objects, while I think both have reasonable use cases, this piece isn’t about the debate.

If everything goes well up until this point, you should be able to tell which users are KYC compliant, which ones are currently in the process of being verified, and those who belong to neither group.
You want to send periodic reminders to the last set of users. This can be in form of emails, in-app pop-ups, push notifications, SMS, whatever. As much as possible, you want to ensure that it does not impact the request/response cycle of users interacting with your app. Again, it’s better to run this flow through a different process, probably in the background.

A rake task would be useful for defining operations that would be scheduled for the periodic reminders. You might be tempted to put all the associated logic in the rake task😈.
This is your coding angel saying ‘Resist that temptation’😇.
Use a PORO (e.g a service object) to make testing easy. If the operation would run for a long time, you should consider using a background process.

By the way, whatever makes testing (specs) easy probably makes debugging easier. Just saying :)

This paradigm isn’t exclusive to Rails. Feel free to adapt as applicable to you.

I hope this gives you some idea of what should be synchronous or asynchronous, what needs to be part of your user flow and what doesn’t, how to ‘hand out responsibilities’ to entities in your codebase, and arrange your files.




Human |

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store