DEV Community

Discussion on: How to best organize a Rails app folder?

Collapse
 
rhymes profile image
rhymes

@bhserna :

my issue with this style (which I have used until recently and trying to move away from) is that you end up with giant modules that contain methods for everything related to "article", it's not that different from the "fat model" pattern.

A better way would be to group stuff by function, not by object, like they do in the labor folder in a way

Collapse
 
bhserna profile image
Benito Serna • Edited

Hi @rhymes =)

More than a module for everything related to "article" (or active record object).... I think that the term "Domain concept" that Andreas used was more accurate...

I don't think is the same as the "fat model" pattern, because also as Andreas said this modules should be used as the API for a domain concept, but you are not forced to implement the behavior there... you can delegate the behavior to other objects/modules inside... maybe something similar to what they do on the labor folder...

And also another difference with the "fat model" is that these modules should not have any state there. This can help you to move the behavior to other modules in and easier way that when you want to move behavior from an stateful object.

Even though is true that this module can grow to something that you don't want and you should be careful...

Two patterns that we have used are...

  1. Have modules for more "concrete concepts"... for examples we have one module Payments but as the application has a lot of behavior in this concept... for some specific concepts related also to payments, we added some other modules like PaymentsStatus, PaymentProjection, MovementsTable, etc...

  2. Delegate to internal module... For example we have a Projects module that have some behavior to keep a budget... At the beginning this behavior was implemented calling classes just one level deep, but then the behavior started to grow and we move the behavior to a Projects::Budgets but we are still calling the behavior through the Projects module...

module Projects
  def self.get_expenses(*args)
    Budgets.get_expenses(*args)
  end
end

Projects.get_expenses(*args)

... And well this method have worked for us, that is why I wanted to share it, but maybe there are other ways that can be better, but we have not tried yet =)

Thread Thread
 
rhymes profile image
rhymes

Thanks for the explanation! Now I understand better :-)

It's more or less what I ended up doing with service objects/modules and "business objects/modules" but something left me unsatisfied and I want to try a better approach the next time around.

I wonder if a tool like dry-auto_inject could help cleaning up the code.