DEV Community

Discussion on: Business logic in Rails with operators

alg profile image
Aleksey Gureiev • Edited on

Good discussion. I replied to your comment without making any assumptions, so there's nothing personal. Made a specific effort not to rely anything said to anyone. And I never suggested to you specifically to read these sources, but to anyone willing to improve their coding-fu. I'm glad we share the library ticket. Now back to the subject.

As for database records sending emails, where did you get that? I was referring to the models. They don't do that. It's not their responsibility (SRP principle). In my systems, their responsibility lies in working with own data. You can hardly call Rails ActiveRecords and ActiveModels anemic as they provide a ton of functionality on top of plain DTOs.

The term "business logic" is so broad that we must be specific about what we call it. When I disagree with placing it into the models I mainly think about business operations. We got used to putting these into app/actions (named by controller "actions", the meat of which was extracted into their own classes). We also have app/services for general-purpose single-responsibility services for low-level operations.

Controllers in our apps look mostly like:

class ChatsController < ...
  def create
    authorize! Chat, to: :create?

    input = convert_input.(Chats::CreateInput, params)
    chat = create_chat.(input, user: current_user)

    respond_with chat
  end
end
Enter fullscreen mode Exit fullscreen mode

Here we shift non-HTTP stuff out of controller into business operations layer where Chats::CreateChatAction belongs. The added benefit of all this is if you ever thought of cutting your monolithic app into now-modern microservices, you already have your code nicely separated into contexts, but that is a different story.

Hope I made my point clear. Just to reiterate, there's no such thing as ideal and true architecture. We attempt to make our systems as manageable, extensible and decoupled as we can. Moving out business operations into a separate layer helps us a lot.

Thread Thread
jaredcwhite profile image
Jared White • Edited on

You:

Business logic should never go inside a model.

Rails:

The Model layer represents the domain model (such as Account, Product, Person, Post, etc.) and encapsulates the business logic specific to your application. In Rails, database-backed model classes are derived from ActiveRecord::Base. Active Record allows you to present the data from database rows as objects and embellish these data objects with business logic methods. Although most Rails models are backed by a database, models can also be ordinary Ruby classes, or Ruby classes that implement a set of interfaces as provided by the Active Model module.

Source:
github.com/rails/rails/blob/main/R...

I think I shall trust what Rails says models are in Rails. 🙂 If you want to extend your own architecture beyond the "Rails way", that's certainly your prerogative, but for any folks out there creating POROs in app/models or even simply using ActiveRecord objects to encapsulate business logic, you are doing exactly what Rails says you should do. I rest my case.