rails: rails 6 lib folder doesn't work
rails 6 lib folder doesn’t work
to reproduce:
rails new my_app
add a file to: lib/my_lib.rb
# lib/my_lib.rb
class MyLib
def self.hello
puts 'Hello'
end
end
rails console
MyLib.hello
NameError: uninitialized constant MyLib
from (pry):1:in `__pry__'
About this issue
- Original URL
- State: closed
- Created 5 years ago
- Comments: 16 (12 by maintainers)
Links to this issue
Commits related to this issue
- Remove eager load config In Rails 6 autoloading is managed by zeitwerk: https://guides.rubyonrails.org/upgrading_ruby_on_rails.html#autoloading Suggested way of getting round this is moving necessar... — committed to alphagov/feedback by cdccollins 4 years ago
- Remove eager load config In Rails 6 autoloading is managed by zeitwerk: https://guides.rubyonrails.org/upgrading_ruby_on_rails.html#autoloading Suggested way of getting round this is moving necessar... — committed to alphagov/feedback by cdccollins 4 years ago
- Remove eager and auto loading In Rails 6 autoloading is managed by zeitwerk: https://guides.rubyonrails.org/upgrading_ruby_on_rails.html#autoloading Suggested way of managing this is moving necessar... — committed to alphagov/licence-finder by cdccollins 4 years ago
- Remove eager and auto loading In Rails 6 autoloading is managed by zeitwerk: https://guides.rubyonrails.org/upgrading_ruby_on_rails.html#autoloading Suggested way of managing this is moving necessar... — committed to alphagov/licence-finder by cdccollins 4 years ago
- Change structure of lib file for new autoloading In Rails 6 autoloading is managed by zeitwerk: https://guides.rubyonrails.org/upgrading_ruby_on_rails.html#autoloading Suggested way of getting round... — committed to alphagov/short-url-manager by cdccollins 4 years ago
- Change structure of lib file for new autoloading In Rails 6 autoloading is managed by zeitwerk: https://guides.rubyonrails.org/upgrading_ruby_on_rails.html#autoloading Suggested way of getting round... — committed to alphagov/short-url-manager by cdccollins 4 years ago
- Change structure of lib file for new autoloading In Rails 6 autoloading is managed by zeitwerk: https://guides.rubyonrails.org/upgrading_ruby_on_rails.html#autoloading Suggested way of getting round... — committed to alphagov/short-url-manager by cdccollins 4 years ago
- Change structure of lib file for new autoloading In Rails 6 autoloading is managed by zeitwerk: https://guides.rubyonrails.org/upgrading_ruby_on_rails.html#autoloading Suggested way of getting round... — committed to alphagov/short-url-manager by cdccollins 4 years ago
- Change structure of files for new autoloading In Rails 6 autoloading is managed by zeitwerk: https://guides.rubyonrails.org/upgrading_ruby_on_rails.html#autoloading Suggested way of getting round th... — committed to alphagov/manuals-publisher by cdccollins 4 years ago
- Change structure of lib file for new autoloading In Rails 6 autoloading is managed by zeitwerk: https://guides.rubyonrails.org/upgrading_ruby_on_rails.html#autoloading Suggested way of getting round... — committed to alphagov/short-url-manager by cdccollins 4 years ago
- Change structure of lib file for new autoloading In Rails 6 autoloading is managed by zeitwerk: https://guides.rubyonrails.org/upgrading_ruby_on_rails.html#autoloading Suggested way of getting round... — committed to alphagov/short-url-manager by cdccollins 4 years ago
- Remove eager and auto loading In Rails 6 autoloading is managed by zeitwerk: https://guides.rubyonrails.org/upgrading_ruby_on_rails.html#autoloading Suggested way of managing this is moving necessar... — committed to alphagov/licence-finder by cdccollins 4 years ago
- Remove eager and auto loading In Rails 6 autoloading is managed by zeitwerk: https://guides.rubyonrails.org/upgrading_ruby_on_rails.html#autoloading Suggested way of managing this is moving necessar... — committed to alphagov/licence-finder by cdccollins 4 years ago
- Remove eager load config In Rails 6 autoloading is managed by zeitwerk: https://guides.rubyonrails.org/upgrading_ruby_on_rails.html#autoloading Suggested way of getting round this is moving necessar... — committed to alphagov/feedback by cdccollins 4 years ago
- Remove eager load config In Rails 6 autoloading is managed by zeitwerk: https://guides.rubyonrails.org/upgrading_ruby_on_rails.html#autoloading Suggested way of getting round this is moving necessar... — committed to alphagov/feedback by cdccollins 4 years ago
- Change structure of files for new autoloading In Rails 6 autoloading is managed by zeitwerk: https://guides.rubyonrails.org/upgrading_ruby_on_rails.html#autoloading Suggested way of getting round th... — committed to alphagov/manuals-publisher by cdccollins 4 years ago
- Change structure of files for new autoloading In Rails 6 autoloading is managed by zeitwerk: https://guides.rubyonrails.org/upgrading_ruby_on_rails.html#autoloading Suggested way of getting round th... — committed to alphagov/manuals-publisher by cdccollins 4 years ago
- Change structure of files for new autoloading In Rails 6 autoloading is managed by zeitwerk: https://guides.rubyonrails.org/upgrading_ruby_on_rails.html#autoloading Suggested way of getting round th... — committed to alphagov/manuals-publisher by cdccollins 4 years ago
A better option is to add an
app/lib
folder which will be auto-loaded and eager-loaded by default without any extra configuration.There are still legitimate cases where someone would want to use the
lib
. Mainly, it is code that is not specific to the application domain. Putting it inapp/lib
seems weird. There are a few concrete cases I use the lib folder for namely: reports, search, analytics, importing, exporting, integration to private apis without a gem.Anything in the lib folder should be extractable to a separate gem and shared with the world.
In a rails 6+ application all you need to do is
Further reading:
I think we can close this one.
The
lib
folder does not belong to the autoload paths since Rails 3. @pixeltrix’s is the recommended modern idiom if you want to autoload.Otherwise,
lib
belongs to$LOAD_PATH
and you canrequire
files in that directory.The
lib
folder does not belong to the autoload paths by default, you need tobefore using
MyLib
.@jeromedalbert that’s right.
Please note that you should also ignore subdirectories that are not meant to be namespaces. For example:
Otherwise, Zeitwerk would define a
Tasks
constant, but that is not your intention (and could potentially conflict with a genuineTasks
constant).Thank you, @yagudaev, the autoload paths worked for me. I think that was my initial thought, I’m not sure why I got turned around about it. Maybe b/c most of the comments in this thread are saying to not do that, or maybe b/c I was thinking I want it to be reloaded, not autoloaded. Not sure, but adding
config.autoload_paths << config.root.join('lib')
is working thus far.Just in case, let me add that
lib
is added to$LOAD_PATH
by Rails automatically.In my view, conceptually there is no probem in making files within
lib
autoloadable and reloadable. There are dozens of gems that use Zeitwerk to load their code (their own instance).You only need to be careful, because if you have
and you put
lib
in as autoload path, you are saying thatlib/tasks
defines the namespaceTasks
. So, you can do that, but you need to be careful. And that was the main reasonlib
was removed from the default autoload paths, because it has a mix of things.You can still have
lib/code
, or tell Zeitwerk to ignorelib/tasks
, but recently people have switched to leave tasks inlib/tasks
, and actual Ruby code inapp/lib
.However, you can pick and choose whatever combination feels better to you, technically a few are possible.
I have worked on apps that put code closely related to the application in
app/
, and code less closely related to the application (i.e. that could be extracted to a gem in the future) inlib/
. Having the two folders separated (and not one included in another) makes sense according to this point of view.So I wanted the app I was working on to work with
lib/
, but I was getting the following error with Rails 6, where the path was truncated:The issue was caused by the last two lines in my
config/application.rb
:Removing those lines to only keep the base paths worked great:
Thanks to @yagudaev for pointing to the right resources.
@JoshCheek are you trying to have a few apps inside of a rails project? What you are describing reminds me of Django which has many apps as it came from publishing so they had many domains/brands.
In rails, this is accomplished with Rails Engines: https://guides.rubyonrails.org/engines.html.
There are a few component types like Models that don’t follow that naming convention. Some gems like graphql, activeadmin also take liberty with it. In this case, omitting it would make sense.
Otherwise the trick I mentioned should work well here it is:
I’m using it here for a live project: https://github.com/yagudaev/search_on_rails_demo/blob/main/lib/search/in_memory.rb#L2 and https://github.com/yagudaev/search_on_rails_demo/blob/main/config/application.rb#L36. It’s a reference implementation of search for a course and new gem I’m working on.
The best practice to accomplish that nowadays is to move that code to
app/lib
. Only the Ruby code you want to reload, tasks or other auxiliary files are OK inlib
.If you do that, there is nothing to configure, it works automatically, and your code base remains simple and standard.
Let me clarify, since we are on it, that “reloading” does not “restart” the server, it only reloads application level code, what’s below
app
to get the idea. The server stays up, initializers do not run again, the operating system process is the same, etc. Only application code is reloaded in memory.@yagudaev I agree that things in
lib/
should be extractable into a separate gem.However I do not think it is correct that files in
lib/
should be auto-loaded, because a plain Ruby gem mustrequire
all of its files explicitly, which does not seem to be compatible with Rails auto-loading semantics.I put “other” code that is app-specific into
app/lib
and assume it will be part of that Rails app permanently (and so I use ActiveSupport extensions etc. in that code). That code is auto-loaded (and reloaded) just fine.For code that I plan to extract into a separate gem at some point, I put it in
lib/
and I add that to$LOAD_PATH
:This means I have to restart my Rails server every time I make changes to files in this directory, which is a pain (and your snippet above does not solve that issue - I just tested in a Rails 6 app). It may work if I remove the
require
statements but then the gem will not work standalone.If there is a way to auto-reload code in
lib/
while being both Rails-compliant and gem-compliant then that would be very useful. Until then I just suck it up and restart my server every time I make a change.