Skip to content

Commit

Permalink
Rename expected_cpath_at to cpath_expected_at
Browse files Browse the repository at this point in the history
After sleeping on it and discussing this method name with @matthewd, I
finally went with `cpath_expected_at`.

`cpath_expected_at` may sound slightly more idiomatic in English and has
the subject, what you ask for, first.
fxn committed Jul 25, 2023

Verified

This commit was signed with the committer’s verified signature. The key has expired.
1 parent 3928654 commit 2cfc3c2
Showing 4 changed files with 47 additions and 47 deletions.
12 changes: 6 additions & 6 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -2,21 +2,21 @@

## 2.6.9 (Unreleased)

* Given a path as a string or `Pathname` object, `Zeitwerk::Loader#expected_cpath_at`
* Given a path as a string or `Pathname` object, `Zeitwerk::Loader#cpath_expected_at`
returns a string with the corresponding expected constant path.

Some examples, assuming that `app/models` is a root directory:

```ruby
loader.expected_cpath_at("app/models") # => "Object"
loader.expected_cpath_at("app/models/user.rb") # => "User"
loader.expected_cpath_at("app/models/hotel") # => "Hotel"
loader.expected_cpath_at("app/models/hotel/billing.rb") # => "Hotel::Billing"
loader.cpath_expected_at("app/models") # => "Object"
loader.cpath_expected_at("app/models/user.rb") # => "User"
loader.cpath_expected_at("app/models/hotel") # => "Hotel"
loader.cpath_expected_at("app/models/hotel/billing.rb") # => "Hotel::Billing"
```

This method returns `nil` for some input like ignored files, and may raise
`Zeitwerk::Error` too. Please check its
[documentation](https://github.com/fxn/zeitwerk#zeitwerkloaderexpected_cpath_at) for
[documentation](https://github.com/fxn/zeitwerk#zeitwerkloadercpath_expected_at) for
further details.

* `Zeitwerk::Loader#load_file` raises a more informative error if given a hidden
26 changes: 13 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
@@ -58,7 +58,7 @@
- [Reopening third-party namespaces](#reopening-third-party-namespaces)
- [Introspection](#introspection)
- [`Zeitwerk::Loader#dirs`](#zeitwerkloaderdirs)
- [`Zeitwerk::Loader#expected_cpath_at`](#zeitwerkloaderexpected_cpath_at)
- [`Zeitwerk::Loader#cpath_expected_at`](#zeitwerkloadercpath_expected_at)
- [Encodings](#encodings)
- [Rules of thumb](#rules-of-thumb)
- [Debuggers](#debuggers)
@@ -1266,40 +1266,40 @@ By default, ignored root directories are filtered out. If you want them included

These collections are read-only. Please add to them with `Zeitwerk::Loader#push_dir`.

<a id="markdown-zeitwerkloaderexpected_cpath_at" name="zeitwerkloaderexpected_cpath_at"></a>
#### `Zeitwerk::Loader#expected_cpath_at`
<a id="markdown-zeitwerkloadercpath_expected_at" name="zeitwerkloadercpath_expected_at"></a>
#### `Zeitwerk::Loader#cpath_expected_at`

Given a path as a string or `Pathname` object, `Zeitwerk::Loader#expected_cpath_at` returns a string with the corresponding expected constant path.
Given a path as a string or `Pathname` object, `Zeitwerk::Loader#cpath_expected_at` returns a string with the corresponding expected constant path.

Some examples, assuming that `app/models` is a root directory:

```ruby
loader.expected_cpath_at("app/models") # => "Object"
loader.expected_cpath_at("app/models/user.rb") # => "User"
loader.expected_cpath_at("app/models/hotel") # => "Hotel"
loader.expected_cpath_at("app/models/hotel/billing.rb") # => "Hotel::Billing"
loader.cpath_expected_at("app/models") # => "Object"
loader.cpath_expected_at("app/models/user.rb") # => "User"
loader.cpath_expected_at("app/models/hotel") # => "Hotel"
loader.cpath_expected_at("app/models/hotel/billing.rb") # => "Hotel::Billing"
```

If `collapsed` is a collapsed directory:

```ruby
loader.expected_cpath_at("a/b/collapsed/c") # => "A::B::C"
loader.expected_cpath_at("a/b/collapsed") # => "A::B", edge case
loader.expected_cpath_at("a/b") # => "A::B"
loader.cpath_expected_at("a/b/collapsed/c") # => "A::B::C"
loader.cpath_expected_at("a/b/collapsed") # => "A::B", edge case
loader.cpath_expected_at("a/b") # => "A::B"
```

If the argument corresponds to an [ignored file or directory](#ignoring-parts-of-the-project), the method returns `nil`. Same if the argument is not managed by the loader.

`Zeitwerk::Error` is raised if the given path does not exist:

```ruby
loader.expected_cpath_at("non_existing_file.rb") # => Zeitwerk::Error
loader.cpath_expected_at("non_existing_file.rb") # => Zeitwerk::Error
```

`Zeitwer::NameError` is raised if a constant path cannot be derived from it:

```ruby
loader.expected_cpath_at("8.rb") # => Zeitwerk::NameError
loader.cpath_expected_at("8.rb") # => Zeitwerk::NameError
```

This method does not parse file contents and does not guarantee files define the returned constant path. It just says which is the _expected_ one.
2 changes: 1 addition & 1 deletion lib/zeitwerk/loader.rb
Original file line number Diff line number Diff line change
@@ -229,7 +229,7 @@ def reload
end

# @sig (String | Pathname) -> String?
def expected_cpath_at(path)
def cpath_expected_at(path)
abspath = File.expand_path(path)

raise Zeitwerk::Error.new("#{abspath} does not exist") unless File.exist?(abspath)
54 changes: 27 additions & 27 deletions test/lib/zeitwerk/test_expected_cpath_at.rb
Original file line number Diff line number Diff line change
@@ -7,7 +7,7 @@ class TestExpectedCpathAtErrors < LoaderTest
test "raises Zeitwerk::Error if the argument does not exist" do
with_setup(dirs: ["."]) do
error = assert_raises Zeitwerk::Error do
loader.expected_cpath_at("does_not_exist.rb")
loader.cpath_expected_at("does_not_exist.rb")
end
abspath = File.expand_path("does_not_exist.rb")
assert_includes error.message, "#{abspath} does not exist"
@@ -21,7 +21,7 @@ class TestExpectedCpathAtErrors < LoaderTest

files.each do |file, _contents|
error = assert_raises Zeitwerk::NameError do
loader.expected_cpath_at(file)
loader.cpath_expected_at(file)
end
abspath = File.expand_path(file)
assert_includes error.message, "cannot derive a constant name from #{abspath}"
@@ -33,7 +33,7 @@ class TestExpectedCpathAtErrors < LoaderTest
with_files([["x/foo-bar/y/z.rb", nil]]) do
loader.push_dir(".")
error = assert_raises Zeitwerk::NameError do
loader.expected_cpath_at("x/foo-bar/y/z.rb")
loader.cpath_expected_at("x/foo-bar/y/z.rb")
end
abspath = File.expand_path("x/foo-bar")
assert_includes error.message, "cannot derive a constant name from #{abspath}"
@@ -46,39 +46,39 @@ class TestExpectedCpathAtNil < LoaderTest
files = [["tasks/database.rake", nil], ["CHANGELOG", nil]]
with_setup(files) do
files.each do |file, _contents|
assert_nil loader.expected_cpath_at(file)
assert_nil loader.cpath_expected_at(file)
end
end
end

test "returns nil if the argument is ignored" do
with_setup([["ignored.rb", nil]]) do
assert_nil loader.expected_cpath_at("ignored.rb")
assert_nil loader.cpath_expected_at("ignored.rb")
end
end

test "returns nil if the argument is a hidden Ruby file" do
with_setup([[".foo.rb", nil]]) do
assert_nil loader.expected_cpath_at(".foo.rb")
assert_nil loader.cpath_expected_at(".foo.rb")
end
end

test "returns nil if the argument does not belong to the autoload paths" do
with_setup(dirs: ["."]) do
assert_nil loader.expected_cpath_at(__dir__)
assert_nil loader.expected_cpath_at(__FILE__)
assert_nil loader.cpath_expected_at(__dir__)
assert_nil loader.cpath_expected_at(__FILE__)
end
end

test "returns nil if an ancestor is ignored" do
with_setup([["ignored/x.rb", nil]]) do
assert_nil loader.expected_cpath_at("ignored/x.rb")
assert_nil loader.cpath_expected_at("ignored/x.rb")
end
end

test "returns nil if an ancestor is a hidden directory" do
with_setup([[".foo/x.rb", nil]]) do
assert_nil loader.expected_cpath_at(".foo/x.rb")
assert_nil loader.cpath_expected_at(".foo/x.rb")
end
end
end
@@ -94,93 +94,93 @@ def self.name

test "returns the name of the root namespace for a root directory (Object)" do
with_setup([["README.md", nil]]) do
assert_equal "Object", loader.expected_cpath_at(".")
assert_equal "Object", loader.cpath_expected_at(".")
end
end

test "returns the name of the root namespace for a root directory (Object, Pathname)" do
with_setup([["README.md", nil]]) do
assert_equal "Object", loader.expected_cpath_at(Pathname.new("."))
assert_equal "Object", loader.cpath_expected_at(Pathname.new("."))
end
end

test "returns the name of the root namespace for a root directory (Custom)" do
with_setup(dirs: ["."], namespace: M) do
assert_equal M_REAL_NAME, loader.expected_cpath_at(".")
assert_equal M_REAL_NAME, loader.cpath_expected_at(".")
end
end

test "returns the name of the root namespace for a root directory (Custom, Pathname)" do
with_setup(dirs: ["."], namespace: M) do
assert_equal M_REAL_NAME, loader.expected_cpath_at(Pathname.new("."))
assert_equal M_REAL_NAME, loader.cpath_expected_at(Pathname.new("."))
end
end

test "returns the name of the root directory even if it is hidden" do
with_setup([[".foo/x.rb", nil]], dirs: [".foo"]) do
assert_equal "Object", loader.expected_cpath_at(".foo")
assert_equal "Object", loader.cpath_expected_at(".foo")
end
end

test "returns the cpath to a root file (Object)" do
with_setup([["x.rb", "X = 1"]]) do
assert_equal "X", loader.expected_cpath_at("x.rb")
assert_equal "X", loader.cpath_expected_at("x.rb")
end
end

test "returns the cpath to a root file (Custom)" do
with_setup([["x.rb", "X = 1"]], namespace: M) do
assert_equal "#{M_REAL_NAME}::X", loader.expected_cpath_at("x.rb")
assert_equal "#{M_REAL_NAME}::X", loader.cpath_expected_at("x.rb")
end
end

test "returns the cpath to a subdirectory (Object)" do
with_setup([["a/x.rb", "A::X = 1"]]) do
assert_equal "A", loader.expected_cpath_at("a")
assert_equal "A", loader.cpath_expected_at("a")
end
end

test "returns the cpath to a subdirectory (Custom)" do
with_setup([["a/x.rb", "A::X = 1"]], namespace: M) do
assert_equal "#{M_REAL_NAME}::A", loader.expected_cpath_at("a")
assert_equal "#{M_REAL_NAME}::A", loader.cpath_expected_at("a")
end
end

test "returns the cpath to a nested file (Object)" do
with_setup([["a/b/c/x.rb", "A::B::C::X = 1"]]) do
assert_equal "A::B::C::X", loader.expected_cpath_at("a/b/c/x.rb")
assert_equal "A::B::C::X", loader.cpath_expected_at("a/b/c/x.rb")
end
end

test "returns the cpath to a nested file (Custom)" do
with_setup([["a/b/c/x.rb", "A::B::C::X = 1"]], namespace: M) do
assert_equal "#{M_REAL_NAME}::A::B::C::X", loader.expected_cpath_at("a/b/c/x.rb")
assert_equal "#{M_REAL_NAME}::A::B::C::X", loader.cpath_expected_at("a/b/c/x.rb")
end
end

test "returns the cpath to a nested directory (Object)" do
with_setup([["a/b/c/x.rb", "A::B::C::X = 1"]]) do
assert_equal "A::B::C", loader.expected_cpath_at("a/b/c")
assert_equal "A::B::C", loader.cpath_expected_at("a/b/c")
end
end

test "returns the cpath to a nested directory (Custom)" do
with_setup([["a/b/c/x.rb", "A::B::C::X = 1"]], namespace: M) do
assert_equal "#{M_REAL_NAME}::A::B::C", loader.expected_cpath_at("a/b/c")
assert_equal "#{M_REAL_NAME}::A::B::C", loader.cpath_expected_at("a/b/c")
end
end

test "supports collapsed directories (Object)" do
with_setup([["a/b/collapsed/x.rb", "A::B::X = 1"]]) do
assert_equal "A::B::X", loader.expected_cpath_at("a/b/collapsed/x.rb")
assert_equal "A::B", loader.expected_cpath_at("a/b/collapsed")
assert_equal "A::B::X", loader.cpath_expected_at("a/b/collapsed/x.rb")
assert_equal "A::B", loader.cpath_expected_at("a/b/collapsed")
end
end

test "supports collapsed directories (Custom)" do
with_setup([["a/b/collapsed/x.rb", "A::B::X = 1"]], namespace: M) do
assert_equal "#{M_REAL_NAME}::A::B::X", loader.expected_cpath_at("a/b/collapsed/x.rb")
assert_equal "#{M_REAL_NAME}::A::B", loader.expected_cpath_at("a/b/collapsed")
assert_equal "#{M_REAL_NAME}::A::B::X", loader.cpath_expected_at("a/b/collapsed/x.rb")
assert_equal "#{M_REAL_NAME}::A::B", loader.cpath_expected_at("a/b/collapsed")
end
end
end

0 comments on commit 2cfc3c2

Please sign in to comment.