The TL;DR answer
You can put any module in /lib
as long as you have autoloading set up properly.
The more nuanced answer
The truth is that you can put your modules anywhere. Personally, my main use for modules is to create namespaces for my Active Record models to help keep things organized. Those module definitions just end up in the same files as my Active Record models.
I have kind of a rule for myself when it comes to Rails file organization. My Rails apps tend to be structures as a mix of Active Record objects and Plain Old Ruby Objects (POROs). The rule is:
If a particular model class (whether it’s an Active Record model class or a PORO model class) pertains specifically to my application, it goes in app/models
. If the model class has nothing specifically to do with my application (e.g. it’s a utility class that could conceivably be open-sourced and used in any application), it goes in lib
.
How to set up autoloading for modules located in /lib
Modify your config/application.rb
to include the following line.
# config/application.rb
module MyApp
class Application < Rails::Application
config.eager_load_paths += %W(#{config.root}/lib)
end
end
Restart your Rails server and you should be good to go.
How to define and include a module
You can define a module like this:
# /lib/foo.rb
module Foo
def hello
"hello"
end
end
When you include that module in a class, you can use the hello
function in the class from which you included the module. See the below for how you would use this Foo
module.
How to use a module in an ActiveRecord model
You can include a module in a class in your Rails project by using the include
keyword followed by the name of your module.
# app/models/customer.rb
class Customer < ActiveRecord::Base
include Foo
end
Now you should be able to do Customer.new.hello
and get “hello” as a result.
Further reading
If you’d like to know more of my thoughts on structuring Rails applications, I’d recommend the following posts.
Extracting a tidy PORO from a messy Active Record model
For organizing Rails projects, domain objects are good and service objects are bad
Thanks! It so helpful for me
Is the autoloading still required/relevant given zeitwerk’s introduction?
doest it affects on production?