Why relative path doesn't work in Ruby require

跟風遠走 提交于 2019-11-29 16:24:17

问题


I'm starting learning Ruby, one thing that I don't understand, why relative path for require directive doesn't work in ruby. It's something that works almost in every scripting language that I now (JSP, PHP...). I explain with a real example. I have a folder named shapes which contains 3 classes shape, rectangle and square. I have also another file test_shapes.rb from where I call and test my classes. When I import my classes to the main file like this:

require "./shape"
require "./rectangle"
require "./square"

I got error for files not found. When I include the name of my subfolder like this:

require "./shapes/shape"
require "./shapes/rectangle"
require "./shapes/square"

The code is perfectly working. Because I specified the whole path to the root directory of the project (the lib folder I think). When I include I include the absolute path to the hard disk, like this:

require "#{File.dirname(__FILE__)}/shape"
require "#{File.dirname(__FILE__)}/rectangle"
require "#{File.dirname(__FILE__)}/square"

It's also working perfectly.

So, I just want some explanation if know why the first import method (the relative path to the current folder) in not working.


回答1:


Relative path is based on working dir. I assume that there is main file on the same directory. If you run ruby ./shapes/main.rb on project root, ruby try to find {project_root}/shape.rb, not {project_root}/shapes/shape.rb. It doesn't work.

You need to use require_relative like below.

# {project_root}/shapes/main.rb
require_relative './shape'
require_relative './rectangle'
require_relative './square'



回答2:


You are using relative path. And they are relative to the place where your script is executed. Generally it is bad idea. You should use either absolute path, either relative path to exact file where require is executed.

require File.expand_path("../shape", __FILE__)

PS: require_relative looks more laconic




回答3:


require(name) → true or false Loads the given name, returning true if successful and false if the feature is already loaded.

If the filename does not resolve to an absolute path, it will be searched for in the directories listed in $LOAD_PATH ($:).

If the filename has the extension “.rb”, it is loaded as a source file; if the extension is “.so”, “.o”, or “.dll”, or the default shared library extension on the current platform, Ruby loads the shared library as a Ruby extension. Otherwise, Ruby tries adding “.rb”, “.so”, and so on to the name until found. If the file named cannot be found, a LoadError will be raised.

For Ruby extensions the filename given may use any shared library extension. For example, on Linux the socket extension is “socket.so” and require 'socket.dll' will load the socket extension.

The absolute path of the loaded file is added to $LOADED_FEATURES ($"). A file will not be loaded again if its path already appears in $". For example, require 'a'; require './a' will not load a.rb again.

require "my-library.rb" require "db-driver" Any constants or globals within the loaded source file will be available in the calling program’s global namespace. However, local variables will not be propagated to the loading environment.

require_relative(string) → true or false Ruby tries to load the library named string relative to the requiring file’s path. If the file’s path cannot be determined a LoadError is raised. If a file is loaded true is returned and false otherwise.

Ref: http://ruby-doc.org/core-2.1.2/Kernel.html#require-method



来源:https://stackoverflow.com/questions/25314237/why-relative-path-doesnt-work-in-ruby-require

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!