I have the following setup where one of my classes includes a module that's located in another file
The key thing to note is that the module MyBar
does not live in a file with a similar name. It lives in my_foo.rb
instead.
module MyBar
def self.test
"This is a test string"
end
end
require 'my_foo'
class SomeClass
include MyBar
def initialize
puts MyBar.test
end
end
When I run this I get a NameError
NameError - uninitialized constant MyBar
It looks like Rails is trying to be smart and assume that because the module name is MyBar
it should be located in a file similarly named my_bar.rb
.
I tried testing this theory by changing the name to what it expects, and it suddenly worked correctly
my_foo.rb (renamed)-> my_bar.rb
The question is
Why does Rails do this? Seems like it's assuming too much. I get that it's "convention over configuration", but there are several valid reasons to have the filename not match the module name.
How do I override this behavior?
The app
directory is not included in $LOAD_PATH
in rails for various reasons (mainly autoloading and class reload while you edit stuff).
If you want to use constants that don't match the file name, you want to locate them in lib
directory and require them (lib
is included in $LOAD_PATH
).
If you really want to include a file in the app
directory, you probably want to try with a require Rails.root.join('app', 'models', 'my_foo.rb').to_s
. I'm not sure what will break though, you are really going against rails convention.
This has something to do with how the autoloading works in Rails.
Rails only auto loads when you try to use a new class/module name that matches the file name and located under the /lib/
directory.
To fix your issue, you can put your my_foo.rb
file under /lib/
directory and require it like this: require 'lib/my_foo'
See the Rails Documentation for Autoloading and Reloading Constants for more information about how auto loading works in Rails.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With