What is the difference between require_relative an

2018-12-31 14:43发布

问题:

What is the difference between require_relative and require in Ruby?

回答1:

Just look at the docs:

require_relative complements the builtin method require by allowing you to load a file that is relative to the file containing the require_relative statement.

For example, if you have unit test classes in the \"test\" directory, and data for them under the test \"test/data\" directory, then you might use a line like this in a test case:

require_relative \"data/customer_data_1\"


回答2:

require_relative is a convenient subset of require

require_relative(\'path\')

equals:

require(File.expand_path(\'path\', File.dirname(__FILE__)))

if __FILE__ is defined, or it raises LoadError otherwise.

This implies that:

  • require_relative \'a\' and require_relative \'./a\' require relative to the current file (__FILE__).

    This is what you want to use when requiring inside your library, since you don\'t want the result to depend on the current directory of the caller.

  • eval(\'require_relative(\"a.rb\")\') raises LoadError because __FILE__ is not defined inside eval.

    This is why you can\'t use require_relative in RSpec tests, which get evaled.

The following operations are only possible with require:

  • require \'./a.rb\' requires relative to the current directory

  • require \'a.rb\' uses the search path ($LOAD_PATH) to require. It does not find files relative to current directory or path.

    This is not possible with require_relative because the docs say that path search only happens when \"the filename does not resolve to an absolute path\" (i.e. starts with / or ./ or ../), which is always the case for File.expand_path.

The following operation is possible with both, but you will want to use require as it is shorter and more efficient:

  • require \'/a.rb\' and require_relative \'/a.rb\' both require the absolute path.

Reading the source

When the docs are not clear, I recommend that you take a look at the sources (toggle source in the docs). In some cases, it helps to understand what is going on.

require:

VALUE rb_f_require(VALUE obj, VALUE fname) {
  return rb_require_safe(fname, rb_safe_level());
}

require_relative:

VALUE rb_f_require_relative(VALUE obj, VALUE fname) {
    VALUE base = rb_current_realfilepath();
    if (NIL_P(base)) {
        rb_loaderror(\"cannot infer basepath\");
    }
    base = rb_file_dirname(base);
    return rb_require_safe(rb_file_absolute_path(fname, base), rb_safe_level());
}

This allows us to conclude that

require_relative(\'path\')

is the same as:

require(File.expand_path(\'path\', File.dirname(__FILE__)))

because:

rb_file_absolute_path   =~ File.expand_path
rb_file_dirname1        =~ File.dirname
rb_current_realfilepath =~ __FILE__


回答3:

From Ruby API:

require_relative complements the builtin method require by allowing you to load a file that is relative to the file containing the require_relative statement.

When you use require to load a file, you are usually accessing functionality that has been properly installed, and made accessible, in your system. require does not offer a good solution for loading files within the project’s code. This may be useful during a development phase, for accessing test data, or even for accessing files that are \"locked\" away inside a project, not intended for outside use.

For example, if you have unit test classes in the \"test\" directory, and data for them under the test \"test/data\" directory, then you might use a line like this in a test case:

require_relative \"data/customer_data_1\" 

Since neither \"test\" nor \"test/data\" are likely to be in Ruby’s library path (and for good reason), a normal require won’t find them. require_relative is a good solution for this particular problem.

You may include or omit the extension (.rb or .so) of the file you are loading.

path must respond to to_str.

You can find the documentation at http://extensions.rubyforge.org/rdoc/classes/Kernel.html



回答4:

Summary

Use require for installed gems

Use require_relative for local files

require uses your $LOAD_PATH to find the files.
require_relative uses the current location of the file using the statement


require

Require relies on you having installed (e.g. gem install [package]) a package somewhere on your system for that functionality.

When using require you can use the \"./\" format for a file in the current directory, e.g. require \"./my_file\" but that is not a common or recommended practice and you should use require_relative instead.

require_relative

This simply means include the file \'relative to the location of the file with the require_relative statement\'. I generally recommend that files should be \"within\" the current directory tree as opposed to \"up\", e.g. don\'t use

require_relative \'../../../filename\'

(up 3 directory levels) within the file system because that tends to create unnecessary and brittle dependencies. However in some cases if you are already \'deep\' within a directory tree then \"up and down\" another directory tree branch may be necessary. More simply perhaps, don\'t use require_relative for files outside of this repository (assuming you are using git which is largely a de-facto standard at this point, late 2018).

Note that require_relative uses the current directory of the file with the require_relative statement (so not necessarily your current directory that you are using the command from). This keeps the require_relative path \"stable\" as it always be relative to the file requiring it in the same way.



回答5:

The top answers are correct, but deeply technical. For those newer to the Ruby--

  • require_relative will most likely be used to bring in code from another file that you wrote.

for example, what if you have data in ~/my-project/data.rb and you want to include that in ~/my-project/solution.rb? in solution.rb you would add require_relative \'data\'.

it is important to note these files do not need to be in the same directory. require_relative \'../../folder1/folder2/data\' is also valid.

  • require will most likely be used to bring in code from a library someone else wrote.

for example, what if you want to use one of the helper functions provided in the active_support library? you\'ll need to install the gem with gem install activesupport and then in the file require \'active_support\'.

require \'active_support/all\'
\"FooBar\".underscore

Said differently--

  • require_relative requires a file specifically pointed to relative to the file that calls it.

  • require requires a file included in the $LOAD_PATH.



回答6:

I just saw the RSpec\'s code has some comment on require_relative being O(1) constant and require being O(N) linear. So probably the difference is that require_relative is the preferred one than require.



回答7:

I want to add that when using windows you can use require \'./1.rb\' if the script is run local or from a mapped network drive but when run from an UNC \\servername\\sharename\\folder path you need to use require_relative \'./1.rb\' I don\'t mingle in the discussion which to use for other reasons.



标签: ruby require