Rails: Loading custom class from lib folder in controller
Asked Answered
K

4

18

I've created a file as lib/services/my_service.rb.

# /lib/services/my_service.rb
class MyService
...
end

I want to use it in app/controllers/my_controller

class MyController < ApplicationController
     def method
          service = MyService.new()
     end

I'm getting an error that MyService is an uninitialized constant. I've tried to import it with

require '/lib/services/my_service.rb'

But I'm getting

cannot load such file -- /lib/services/my_service.rb

Edit: I have tried autoloading from application.rb using

config.autoload_paths << Rails.root.join('lib')

But no dice. Still getting uninitialized constant MyController::MyService

Kulak answered 5/11, 2017 at 8:44 Comment(0)
T
36

Ruby on Rails requires following certain naming conventions to support autoloading.

Rails can autoload a file located at lib/services/my_service.rb if the model/class structure was Services::MyService.

Change your lib/services/my_service.rb to:

module Services
  class MyService
    # ...
  end
end

And use that class like this in your controller:

service = Services::MyService.new

Please note that depending on your Ruby on Rails version, you might need to add the lib folder to the list of folders which are queried when looking for a file to autoload:

# add this line to your config/application.rb:
config.autoload_paths << "#{Rails.root}/lib"

Read more about autoloading in the Rails Guides.

Testate answered 5/11, 2017 at 8:52 Comment(2)
This solved it without having to explicitly require. Thanks for that.Kulak
I had the same issue, but Services::MyService.new wasn't required after application.rb was updated and server was restarted. I was able to access my custom class with MyService.new() from the controller.Scarborough
G
10

You probably need to enable the autoload from the files in the lib/ folder:

# config/application.rb
config.autoload_paths << "#{Rails.root}/lib"

If you prefer to do it "manually", then you can only require such file in the same file:

# config/application.rb
require './lib/my_service'

After this a restart is necessary.

Gamut answered 5/11, 2017 at 8:48 Comment(3)
Tried that already to autoload it. Still getting uninitialized constant MyController::MyServiceKulak
Try then with require './lib/my_service' and restarting your server.Cacology
Seems like the dot at the beginning of the require statement fixed it. Thanks!Kulak
F
1

there is a setting in config/application.rb in which you can specify directories that contain files you want autoloaded.

From application.rb:

# Custom directories with classes and modules you want to be autoloadable.
# config.autoload_paths += %W(#{config.root}/extras)

or

config.autoload_paths += Dir["#{config.root}/lib/**/"]

rails 3

Dir["lib/**/*.rb"].each do |path|
  require_dependency path
end 
Fishing answered 5/11, 2017 at 9:12 Comment(0)
R
1

Add this in your application.rb

config.eager_load_paths << Rails.root.join('lib/services')
Reggi answered 3/9, 2020 at 21:31 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.