Way to load folder as module constant in rails app directory
Asked Answered
C

1

10

So have a rails 5 project and would like to load a directory like this

/app
  /services
    /user
      foo.rb

as the constant ::Services::User::Foo

Does anyone have experience in getting rails autoload paths to load the constants in this manner?


foo.rb

module Services
  module User
    class Foo

    end
  end
end

SOLUTION

Add this to your application.rb file

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

See discussions here on autoloading

https://github.com/rails/rails/issues/14382#issuecomment-37763348 https://github.com/trailblazer/trailblazer/issues/89#issuecomment-149367035

Cralg answered 1/12, 2016 at 21:50 Comment(3)
What's inside foo.rb? A class, a module, loose methods?Nubilous
How is the class named? Foo, not inside a module?Nubilous
It would be a class that is underneath the modules (Services::User), just updated question with exampleCralg
N
12

Auto loading

You need to define Services::User::Foo inside app/services/services/user/foo.rb

If you don't want this weird subfolder duplication, you could also move services to app/models/services or lib/services.

You could also leave foo.rb in app/services/user/foo.rb, but it should define User::Foo.

Eager loading

If you don't need any magic with namespaces and class names, it is pretty straightforward :

Dir[Rails.root.join('app/services/**/*.rb')].each{|rb| require rb}

This will eagerly load any Ruby script inside app/services and any subfolder.

Nubilous answered 1/12, 2016 at 22:22 Comment(7)
Thanks for taking the time to answer, i am wanting this to go with the autoload paths so that it is reloaded on file changes, when i do this config.autoload_paths += Dir[File.join(Rails.root,'app/services')] the constants don't show upCralg
For the Autoloading example above, that should work out of the box without having to add to the autoload_paths b/c all folders in the app directory are there by default. My thought was that there had to be a way to do that without the double nestingCralg
Subfolders in app are not treated equally. app/models/user.rb does not define Models::User but just User for example.Nubilous
Cool, i see/understand what you are saying. I was thinking that there might be some way to tell ActiveSupport to load a folder as a module.Cralg
github.com/rails/rails/issues/14382#issuecomment-37763348 this may do it, will check here in a bit and updateCralg
No need to add config.autoload_paths << Rails.root.join('app/services') actually.Nubilous
Adding config.autoload_paths << Rails.root.join('app') does the trick that will load the services folder as a module and loads all the other stuff normally (models/controllers/etc)Cralg

© 2022 - 2024 — McMap. All rights reserved.