Reputation: 6119
A require
d Ruby file isn't finding a constant in another file in the same location, I suspect because of the order Ruby receives the files from the filesystem when using Dir.each
. Different behaviour occurs on different machines/OSes. Is there a filesystem independent approach to using require?
In a rails app with rspec we have a spec_helper that requires everything under spec/support
:
Dir[Rails.root.join("spec/support/**/*.rb")].each { |f| require f }
In a module under that tree, Class A inherits from B, but on one machine (MacOS) a.rb
is required before b.rb
and dies because it can't find A. On another machine (Ubuntu) there is no problem. In fact I can't see a good reason why it should work on that machine.
#a.rb
puts "required A"
module MyModule
class A < B
end
end
#b.rb
puts "required B"
module MyModule
class B
end
end
When the specs run on the Mac, the Dir.each {require}
causes the following output:
required A
/Users/me/myproject/spec/support/mymodule/a.rb:4:in `<module:MyModule>': uninitialized constant MyModule::B (NameError)
On the Ubuntu machine, we have
required B
required A
... no error. Since it's not alphabetic I guess that the Ruby on Ubuntu is getting the files on something other than filename, perhaps on timestamp or physical position on the disk. Both of these seem quite tenuous.
Upvotes: 1
Views: 211
Reputation: 1230
Explicitly require b from inside a:
#a.rb
require 'b'
puts "required A"
module MyModule
class A < B
end
end
This will guarantee that b is always required before a, regardless of operating system load order.
Upvotes: 1
Reputation: 3626
It's just an array, so you could just do this:
Dir[Rails.root.join("spec/support/**/*.rb")].sort.reverse.each { |f| require f }
Then ensure that dependencies are met in the correct order.
Upvotes: 0