The key thing to understand is that imports (requires) in Ruby are global.
Under the hood Rails is requiring application record and then requiring your model files. Since application record was required already (albeit in a different file), the models, and all other bits of code loaded thereafter, have access to it.
You can see this in the following simple example:
# a.rb
require 'b'
require 'c'
# b.rb
class ThisIsExported; end
# c.rb
puts defined?(ThisisExported) # => 'constant'
Remember that classes, modules, and constants are all globals (although they can be namespaced), and that these are the only things 'exported' from a file (well, naked methods can also be exported, but these are actually defined on a global Object instance). So, requiring a file in Ruby is not so much 'importing' it to a specific file, but rather like calling 'eval' on that file's source code.
You can think of it as as if Ruby is just find-and-replacing all require calls with that file's actual source code ... this isn't actally what's happening but the effect is the same.
The closest thing Ruby has to strictly file-specific imports are refinements, but you still need to package those up into a global anyway, and the behaviour is not entirely consistent with regular imports (for example defined?
will not be accurate)
# a.rb
require 'b'
require 'c'
require 'd'
# b.rb
module FileSpecificModuleInclude
refine(Object) do
def patched; 'ok'; end
end
end
# c.rb
using FileSpecificModuleInclude
# It says it's not defined ....
puts defined?(patched) # => nil
# But it actually is ...
puts patched # => 'ok'
# d.rb
patched # => NoMethodError