[ruby-core:114796] [Ruby master Feature#19889] Let `Kernel.#require` search for files relative to the current working directory for non ./, ../ relative paths

Issue #19889 has been reported by sawa (Tsuyoshi Sawada). ---------------------------------------- Feature #19889: Let `Kernel.#require` search for files relative to the current working directory for non ./, ../ relative paths https://bugs.ruby-lang.org/issues/19889 * Author: sawa (Tsuyoshi Sawada) * Status: Open * Priority: Normal ---------------------------------------- My understanding is that `./` and `../` in the given path argument are interpreted relative to: (1) * The current working directory (for `load` or `require`) * The requiring file's path (for `require_relative`) which shows a division of labor between the methods, and seems reasonable. However, when it comes to other relative paths (e.g., `foo/bar.rb`), they are interpreted relative to: (2) * Paths in `$LOAD_PATH` (for `require`) * Paths in `$LOAD_PATH` or **the current working directory** (for `load` or `require_relative`) The search path in (2) for `require` is a proper subset of that of `load` and `require_relative`. There is no division of labor here; there is only inconvenience for `require`. Furthermore, in (1), `require` (as well as `load`) is concerned with the current working directory while `require_relative` is not, but in (2), the relation is reversed: `require_relative` (as well as `load`) is concerned with the current working directory while `require` is not. This situation is making the specification of `relative` versus `require_relative` difficult to understand, as well as inconvenience. **Proposal**: For non-`./`-or-`../` relative paths, I propose to let `Kernel.#require` search relative to the current working directory if the file is not found relative to the paths in `$LOAD_PATH`, so that the methods `load`, `require`, and `require_relative` all work the same in this respect. -- https://bugs.ruby-lang.org/

Issue #19889 has been updated by nobu (Nobuyoshi Nakada). Status changed from Open to Feedback sawa (Tsuyoshi Sawada) wrote:
My understanding is that `./` and `../` in the given path argument are interpreted relative to:
(1) * The current working directory (for `load` or `require`) * The requiring file's path (for `require_relative`)
The former is correct, the latter is wrong. Always `./` means the current working directory, never the loading file's directory.
**Proposal**: For non-`./`-or-`../` relative paths, I propose to let `Kernel.#require` search relative to the current working directory if the file is not found relative to the paths in `$LOAD_PATH`, so that the methods `load`, `require`, and `require_relative` all work the same in this respect.
You can add `"."` to `$LOAD_PATH`, at your own risk. Historically, `$LOAD_PATH` contained `"."` if `$SAFE` is 0, but it was totally removed in 2009 for security reasons. I don't think we will revise it. ---------------------------------------- Feature #19889: Let `Kernel.#require` search for files relative to the current working directory for non ./, ../ relative paths https://bugs.ruby-lang.org/issues/19889#change-104644 * Author: sawa (Tsuyoshi Sawada) * Status: Feedback * Priority: Normal ---------------------------------------- My understanding is that `./` and `../` in the given path argument are interpreted relative to: (1) * The current working directory (for `load` or `require`) * The requiring file's path (for `require_relative`) which shows a division of labor between the methods, and seems reasonable. However, when it comes to other relative paths (e.g., `foo/bar.rb`), they are interpreted relative to: (2) * Paths in `$LOAD_PATH` (for `require`) * Paths in `$LOAD_PATH` or **the current working directory** (for `load` or `require_relative`) For example, given: * File `some_path/foo/a.rb` * File `some_path/b.rb` with content `require "foo/a"` * Current directory at `some_path`, running `ruby b.rb` raises a `LoadError`, but given: * File `some_path/foo/a.rb` * File `some_path/b.rb` with content ` require_relative "foo/a"` * Current directory at `some_path`, running `ruby b.rb` does not raise an error. The search path in (2) for `require` is a proper subset of that of `load` and `require_relative`. There is no division of labor here; there is only inconvenience for `require`. Furthermore, in (1), `require` (as well as `load`) is concerned with the current working directory while `require_relative` is not, but in (2), the relation is reversed: `require_relative` (as well as `load`) is concerned with the current working directory while `require` is not. This situation is making the specification of `require` versus `require_relative` difficult to understand, as well as causing inconvenience. **Proposal**: For non-`./`-or-`../` relative paths, I propose to let `Kernel.#require` search relative to the current working directory if the file is not found relative to the paths in `$LOAD_PATH`, so that the methods `load`, `require`, and `require_relative` all work the same in this respect. -- https://bugs.ruby-lang.org/

Issue #19889 has been updated by rubyFeedback (robert heiler). sawa wrote:
This situation is making the specification of require versus require_relative difficult to understand, as well as causing inconvenience.
I kind of stay(ed) with require and almost never use require_relative. So for me at the least it is not really an issue. Other ruby devs use require_relative fine in their gems and code. I guess it is a matter of preference and how you want to work with extension-code you write in ruby. For me it seemed easier to think of every extensions as a gem, at the least when possible, and there I can do require 'name_of_the_gem/first_file_to_load.rb', which then may load all the other .rb files. As for ./ and ../ - I kind of try to ignore them completely, and when I get a listing of a directory content or absolute path, I try to always store directories, or rather name of directories, with a trailing '/'. My mind just prefers to see a trailing '/' whenever I work with a directory. In many of my projects, under base/base.rb, I tend to add a method such as "def pwd" or "def return_pwd", that is basically Dir.pwd but also ensures there is one trailing /. This may seem rather pointless, but I kind of like to use it consistently, and not rely on Dir.pwd directly. I also try to use File.absolute_path() when it is feasible, even if it may not be absolutely necessary. It just seems easier for me to rely on such awkward patterns. On the other hand I (almost) never modify $LOAD_PATH; I think I only do so for irbrc or so; other than that I try to just let ruby handle $LOAD_PATH for me. At the least most of the time. sawa wrote:
Proposal: For non-./-or-../ relative paths, I propose to let Kernel.#require search relative to the current working directory if the file is not found relative to the paths in $LOAD_PATH, so that the methods load, require, and require_relative all work the same in this respect.
I somewhat understand the thought process here, even more so as I myself try to avoid require_relative. :) But I think, people can use just require() too, or? For some of the ruby code I use locally, such as, a simple example, the file at strategeme/strategeme.rb, I have: require_relative 'common.rb' And this is then a local .rb file I use to power all the other ruby code that is solely for local use. The rest I tend to publish freely available on rubygems.org, where I don't need to use require_relative. Interestingly some ruby gems seem to prefer require_relative, e. g. webrick: httpservlet.rb # require_relative 'httpservlet/filehandler' In such cases I just use require directly rather than require_relative. But functionality-wise, I think both achieve just about the same? ---------------------------------------- Feature #19889: Let `Kernel.#require` search for files relative to the current working directory for non ./, ../ relative paths https://bugs.ruby-lang.org/issues/19889#change-104715 * Author: sawa (Tsuyoshi Sawada) * Status: Feedback * Priority: Normal ---------------------------------------- My understanding is that `./` and `../` in the given path argument are interpreted relative to: (1) * The current working directory (for `load` or `require`) * The requiring file's path (for `require_relative`) which shows a division of labor between the methods, and seems reasonable. However, when it comes to other relative paths (e.g., `foo/bar.rb`), they are interpreted relative to: (2) * Paths in `$LOAD_PATH` (for `require`) * Paths in `$LOAD_PATH` or **the current working directory** (for `load` or `require_relative`) For example, given: * File `some_path/foo/a.rb` * File `some_path/b.rb` with content `require "foo/a"` * Current directory at `some_path`, running `ruby b.rb` raises a `LoadError`, but given: * File `some_path/foo/a.rb` * File `some_path/b.rb` with content ` require_relative "foo/a"` * Current directory at `some_path`, running `ruby b.rb` does not raise an error. The search path in (2) for `require` is a proper subset of that of `load` and `require_relative`. There is no division of labor here; there is only inconvenience for `require`. Furthermore, in (1), `require` (as well as `load`) is concerned with the current working directory while `require_relative` is not, but in (2), the relation is reversed: `require_relative` (as well as `load`) is concerned with the current working directory while `require` is not. This situation is making the specification of `require` versus `require_relative` difficult to understand, as well as causing inconvenience. **Proposal**: For non-`./`-or-`../` relative paths, I propose to let `Kernel.#require` search relative to the current working directory if the file is not found relative to the paths in `$LOAD_PATH`, so that the methods `load`, `require`, and `require_relative` all work the same in this respect. -- https://bugs.ruby-lang.org/

Issue #19889 has been updated by vo.x (Vit Ondruch). I think that the biggest issue is with `require_relative` and expansion of the relative paths to absolute paths. What it should actually do IMHO is add the current directory, form which the relativeness is derived, to the `$LOAD_PATH` and use the usual `require` afterwards. ---------------------------------------- Feature #19889: Let `Kernel.#require` search for files relative to the current working directory for non ./, ../ relative paths https://bugs.ruby-lang.org/issues/19889#change-104716 * Author: sawa (Tsuyoshi Sawada) * Status: Feedback * Priority: Normal ---------------------------------------- My understanding is that `./` and `../` in the given path argument are interpreted relative to: (1) * The current working directory (for `load` or `require`) * The requiring file's path (for `require_relative`) which shows a division of labor between the methods, and seems reasonable. However, when it comes to other relative paths (e.g., `foo/bar.rb`), they are interpreted relative to: (2) * Paths in `$LOAD_PATH` (for `require`) * Paths in `$LOAD_PATH` or **the current working directory** (for `load` or `require_relative`) For example, given: * File `some_path/foo/a.rb` * File `some_path/b.rb` with content `require "foo/a"` * Current directory at `some_path`, running `ruby b.rb` raises a `LoadError`, but given: * File `some_path/foo/a.rb` * File `some_path/b.rb` with content ` require_relative "foo/a"` * Current directory at `some_path`, running `ruby b.rb` does not raise an error. The search path in (2) for `require` is a proper subset of that of `load` and `require_relative`. There is no division of labor here; there is only inconvenience for `require`. Furthermore, in (1), `require` (as well as `load`) is concerned with the current working directory while `require_relative` is not, but in (2), the relation is reversed: `require_relative` (as well as `load`) is concerned with the current working directory while `require` is not. This situation is making the specification of `require` versus `require_relative` difficult to understand, as well as causing inconvenience. **Proposal**: For non-`./`-or-`../` relative paths, I propose to let `Kernel.#require` search relative to the current working directory if the file is not found relative to the paths in `$LOAD_PATH`, so that the methods `load`, `require`, and `require_relative` all work the same in this respect. -- https://bugs.ruby-lang.org/

Issue #19889 has been updated by vo.x (Vit Ondruch). In short, this could be the implementation: ~~~ def require_relative(path) $LOAD_PATH.unshift __dir__ require path $LOAD_PATH.shift end ~~~ Anything else breaks is harmful (talking about issues such as #16978 which is related IMHO). ---------------------------------------- Feature #19889: Let `Kernel.#require` search for files relative to the current working directory for non ./, ../ relative paths https://bugs.ruby-lang.org/issues/19889#change-104722 * Author: sawa (Tsuyoshi Sawada) * Status: Feedback * Priority: Normal ---------------------------------------- My understanding is that `./` and `../` in the given path argument are interpreted relative to: (1) * The current working directory (for `load` or `require`) * The requiring file's path (for `require_relative`) which shows a division of labor between the methods, and seems reasonable. However, when it comes to other relative paths (e.g., `foo/bar.rb`), they are interpreted relative to: (2) * Paths in `$LOAD_PATH` (for `require`) * Paths in `$LOAD_PATH` or **the current working directory** (for `load` or `require_relative`) For example, given: * File `some_path/foo/a.rb` * File `some_path/b.rb` with content `require "foo/a"` * Current directory at `some_path`, running `ruby b.rb` raises a `LoadError`, but given: * File `some_path/foo/a.rb` * File `some_path/b.rb` with content ` require_relative "foo/a"` * Current directory at `some_path`, running `ruby b.rb` does not raise an error. The search path in (2) for `require` is a proper subset of that of `load` and `require_relative`. There is no division of labor here; there is only inconvenience for `require`. Furthermore, in (1), `require` (as well as `load`) is concerned with the current working directory while `require_relative` is not, but in (2), the relation is reversed: `require_relative` (as well as `load`) is concerned with the current working directory while `require` is not. This situation is making the specification of `require` versus `require_relative` difficult to understand, as well as causing inconvenience. **Proposal**: For non-`./`-or-`../` relative paths, I propose to let `Kernel.#require` search relative to the current working directory if the file is not found relative to the paths in `$LOAD_PATH`, so that the methods `load`, `require`, and `require_relative` all work the same in this respect. -- https://bugs.ruby-lang.org/

Issue #19889 has been updated by vo.x (Vit Ondruch). Actually this could be even better and more in line with current implementation: ~~~ruby def require_relative(path) original_load_path = $LOAD_PATH.dup $LOAD_PATH.replace [__dir__] require path $LOAD_PATH.replace original_load_path end ~~~ ---------------------------------------- Feature #19889: Let `Kernel.#require` search for files relative to the current working directory for non ./, ../ relative paths https://bugs.ruby-lang.org/issues/19889#change-104723 * Author: sawa (Tsuyoshi Sawada) * Status: Feedback * Priority: Normal ---------------------------------------- My understanding is that `./` and `../` in the given path argument are interpreted relative to: (1) * The current working directory (for `load` or `require`) * The requiring file's path (for `require_relative`) which shows a division of labor between the methods, and seems reasonable. However, when it comes to other relative paths (e.g., `foo/bar.rb`), they are interpreted relative to: (2) * Paths in `$LOAD_PATH` (for `require`) * Paths in `$LOAD_PATH` or **the current working directory** (for `load` or `require_relative`) For example, given: * File `some_path/foo/a.rb` * File `some_path/b.rb` with content `require "foo/a"` * Current directory at `some_path`, running `ruby b.rb` raises a `LoadError`, but given: * File `some_path/foo/a.rb` * File `some_path/b.rb` with content ` require_relative "foo/a"` * Current directory at `some_path`, running `ruby b.rb` does not raise an error. The search path in (2) for `require` is a proper subset of that of `load` and `require_relative`. There is no division of labor here; there is only inconvenience for `require`. Furthermore, in (1), `require` (as well as `load`) is concerned with the current working directory while `require_relative` is not, but in (2), the relation is reversed: `require_relative` (as well as `load`) is concerned with the current working directory while `require` is not. This situation is making the specification of `require` versus `require_relative` difficult to understand, as well as causing inconvenience. **Proposal**: For non-`./`-or-`../` relative paths, I propose to let `Kernel.#require` search relative to the current working directory if the file is not found relative to the paths in `$LOAD_PATH`, so that the methods `load`, `require`, and `require_relative` all work the same in this respect. -- https://bugs.ruby-lang.org/
participants (4)
-
nobu (Nobuyoshi Nakada)
-
rubyFeedback (robert heiler)
-
sawa (Tsuyoshi Sawada)
-
vo.x (Vit Ondruch)