Adding a directory to the load path in Rails?
Asked Answered
C

9

71

As of Rails 2.3, what's the right way to add a directory to the load path so that it hooks into Rails' auto-reloading mechanisms?

The specific example I'm thinking of is I have a class that has several sub-classes using STI and I thought it would be a good idea to put them in a sub-directory rather than clutter the top-level. So I would have something like:

#app/models/widget.rb
class Widget < ActiveRecord::Base
   add_to_load_path File.join(File.dirname(__FILE__), "widgets")
end

#app/models/widgets/bar_widget.rb
class BarWidget < Widget
end

#app/models/widgets/foo_widget.rb
class FooWidget < Widget
end

It's the add_to_load_path method that I'm looking for.

Candytuft answered 3/8, 2009 at 17:11 Comment(0)
D
117

In the current version of Rails (3.2.8), this has been changed in the application.rb file.

The code is currently commented out as:

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

Will need to update the autoload_paths value. Attempting to modify the the former load_paths variable causes this error.

/configuration.rb:85:in `method_missing': undefined method `load_paths' for #<Rails::Application::Configuration:0xac670b4> (NoMethodError)

for an example, for each path to add to autoload_paths config, add a line similar to the following:

config.autoload_paths += %W(#{config.root}/app/validators)

config.autoload_paths accepts an array of paths from which Rails will autoload constants. Default is all directories under app.

http://guides.rubyonrails.org/configuring.html


From commentor (hakunin) below:

If the directory is under app/, you don't need to add it anywhere, it should just work by default (definitely in 3.2.12). Rails has eager_load_paths that acts as autoload_paths in development, and eager load in production. All app/* directories are automatically added there.

Darceldarcey answered 10/10, 2012 at 18:44 Comment(10)
You are answering a 3 year old question, and rails 3 did not exists when this question was askedTragedy
Bro, you know the search engine Google, it lists 3 year old search results-all the time. Wouldn't it be nice if the 3 year old result could answer your question and end your quest sooner?Darceldarcey
Of course, but this question has an accepted answer already, so the questioner already got an answer to his question.Tragedy
@Tragedy - StackOverflow is intended to be a repository of question and answers that are relevant and applicable at all times. When things change (ie. version updates), answers should be updated appropriately or new answers given. pocket-full-of-quarters did the right thing.Stanislaw
for the record I am very glad this response was posted. The accepted answer is no longer correct.Jolee
Thanks for taking the time to answer this old question - you definitely saved me time. I hate how many people on this site think it should work the way they believe it should.Saccharometer
If the directory is under app/, you don't need to add it anywhere, it should just work by default (definitely in 3.2.12). Rails has eager_load_paths that acts as autoload_paths in development, and eager load in production. All app/* directories are automatically added there.Dwayne
This is when I really wish I could down vote a comment.Jerrome
For anyone wondering, @hakunin's comment still holds true for Rails 4. Any directory added in app/* will work.Selwyn
This does not seem to work in Rails 6. I added rb files to a path app/controllers/viewmodels, and ruby has no idea they exist. I also have to restart the puma server every time I change one, unlike everything else which detects changes fine.Microcyte
L
64

For older versions of Rails:

You can do this in your environment.rb config file.

config.load_paths << "#{RAILS_ROOT}/app/widgets"

--

For Rails 3, see answers bellow

Labarum answered 3/8, 2009 at 17:16 Comment(2)
ActiveSupport::Dependencies.autoload_paths << "#{RAILS_ROOT}/app/widgets"Stinky
See answer by pocket-full-of-quarters which is actually correct. This one is now out of date.Hightail
A
33

In Rails 5 you don't have to explicitly load folders from within the app directory anymore. All folders placed inside are directly available. You don't have to touch any of the config files. But it seems as if there are some issues with Spring.

The new workflow therefore is:

  1. create a new folder and class inside the /app directory
  2. run spring stop on the command line
  3. check the autoload-paths with bin/rails r 'puts ActiveSupport::Dependencies.autoload_paths' on the command line. The new folder should now be listed.
  4. run spring start on the command line
Alaniz answered 15/2, 2017 at 17:1 Comment(6)
I am finding this one unreliable & I never had spring installed or in my gemfile (when executed). By unreliable I mean the puts code finds the directory but none of the files in it are loaded to include elsewhere. Including classes does work for me when I put the autoload_path in the config/application.rb instead.Basilius
@Mirv - which rails version are you on? and have a look at: guides.rubyonrails.org/…Alaniz
Yea, I read those & then tested on rails 5.0.0 & 5.1.0 in cloud9's IDE. It apparently doesn't handle like normal changes to the files when running rails s, but instead I have to reload! while in rails c, which isn't mentioned for 3 more sections of the documentation! I went back & checked, right now as it stands for my project - I have to manually add the file even though it's located in app/classes/filler.rb while using rails c ... I even restarted the workspace, though I haven't started a completely fresh project.Basilius
works for me, thanks. spring server is correct for 2019 instead of spring startDiena
Oh spring... Thanks! You saved me.Unborn
thanks man, you saved my time.Coastal
C
27

In Rails 3, you can set this in config/application.rb, where this sample is provided by default:

# Add additional load paths for your own custom dirs
# config.load_paths += %W( #{config.root}/extras )
Chukker answered 6/9, 2010 at 16:51 Comment(1)
# config.autoload_paths += %W(#{config.root}/extras)Humbug
A
13

On Rails 5 you need to add the following code to environment.rb:

# Add the widgets folder to the autoload path
Rails.application.configure do
  config.autoload_paths << "#{Rails.root}/app/widgets"
end
Apoplectic answered 3/9, 2016 at 21:44 Comment(2)
Rails 5 actually autoloads all folders in the app directory.Alaniz
Thanks. This was the default behaviour last time I checked, but honestly I can't remember if it was a production only issue like stated in here: blog.bigbinary.com/2016/08/29/…Apoplectic
R
8

Another update for rails 3 -- activesupport 3.0.0:

Instead of:

ActiveSupport::Dependencies.load_paths << "#{RAILS_ROOT}/app/widgets"

You may need to do this:

ActiveSupport::Dependencies.autoload_paths << "#{RAILS_ROOT}/app/widgets"
Reareace answered 12/10, 2010 at 22:51 Comment(2)
Rails.root is necessary in Rails 3 instead of RAILS_ROOTPentaprism
Under Rails 3.0.3, I had to use ActiveSupport::Dependencies.autoload_paths += %W( #{Rails.root.to_s}/app/libs )Report
D
1

I found I needed to do this after config block-- no access to config object anymore.

This did the trick

ActiveSupport::Dependencies.load_paths << "#{RAILS_ROOT}/app/widgets"
Deprivation answered 26/9, 2009 at 21:30 Comment(1)
doesn't work on Rails 6, see methods with ActiveSupport::Dependencies.methodsNisse
T
1

In config/application.rb add config.autoload_paths << "#{config.root}/models/widgets".

File should look like this:

module MyApp
  class Application < Rails::Application
    config.autoload_paths << "#{config.root}/models/widgets"
  end
end

I know this works for Rails 4 and 5. Probably others as well.

Teuton answered 10/10, 2017 at 20:33 Comment(0)
M
1

If you want to add multiple directories:

config.autoload_paths += Dir[Rails.root / "components/*/app/public"]

(this is an example for packwerk autoload)

Multifold answered 25/3, 2021 at 22:20 Comment(1)
Thanks Dorian this is exactly what i needed to do (specifically for packwerk) and I spent over an hour trying to get it working! Thanks for sharingMaros

© 2022 - 2024 — McMap. All rights reserved.