Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Autoloading from subdirectory with same name as ruby file doesn't work #31

Closed
schuetzm opened this issue Mar 22, 2019 · 10 comments
Closed

Comments

@schuetzm
Copy link

Autoloading doesn't seem to work with a file hierarchy like this:

app/models/book.rb          Book
app/models/book/bla.rb      Book::Bla < Book

How to reproduce:

mkdir /tmp/zw && cd /tmp/zw
rails new .
echo "class Book ; end" > app/models/book.rb
mkdir app/models/book
echo "class Book::Bla < Book ; end" > app/models/book/bla.rb
rails console

Then, trying to access Book::Bla does not autoload app/models/book/bla.rb:

Loading development environment (Rails 6.0.0.beta3)
2.5.1 :001 > Book
 => Book 
2.5.1 :002 > Book::Bla
Traceback (most recent call last):
        1: from (irb):2
NameError (uninitialized constant Book::Bla)
@casperisfine
Copy link
Contributor

I tested with the following test case:

  test "autoloads inheriting from parent namespace" do
    files = [
      ["a.rb", "class A; end"],
      ["a/x.rb", "class A::X < A; end"],
    ]
    with_setup(files) do
      assert A::X
    end
  end

It works fine.

However since this is an explicit namespace, I think it's likely you are being hit by the ISeq loading not triggering TracePoint callbacks.

Can you try disabling bootsnap in config/boot.rb and retry ? This is a known issue and we're waiting for a fix from MRI.

@fxn
Copy link
Owner

fxn commented Mar 22, 2019

Sure, see rails/rails#35475 for background and some workarounds.

@fxn
Copy link
Owner

fxn commented Mar 22, 2019

Closing here, since Zeitwerk itself is good, and that issue in Rails has it covered.

@fxn fxn closed this as completed Mar 22, 2019
@schuetzm
Copy link
Author

@casperisfine Thanks, it indeed works without bootsnap.

@bibendi
Copy link

bibendi commented Apr 4, 2019

It seems when I use pry-byebug the autoload still have this problem. The problem appears when I'm trying to debug when entering to binding.pry at some point of code.

I have these files:

app/graphql/types.rb

module Types
  ...
end

app/graphql/types/base.rb

module Types
  class Base
  ...
end
require "pry-byebug"
...
binding.pry
> [1] pry(#<RSpec::ExampleGroups::MeChatRooms>)> Types::Base
NameError: uninitialized constant Types::Base

Without pry-byebug all worked fine.

I have Ruby 2.6.1 and Rails 6 beta 3.

@fxn
Copy link
Owner

fxn commented Apr 4, 2019

Can you reproduce that in a minimal pure Ruby setup?

@palkan
Copy link

palkan commented Apr 4, 2019

@fxn More information for the case above:

[19] pry(#<RSpec::ExampleGroups::PerkIdId>)> PerksBy::Types::Perk
NameError: uninitialized constant PerksBy::Types::Perk
Did you mean?  PerksBy::Perk
               PerksBy::Perks

[20] pry> Zeitwerk::Registry.loaders
=> [#<Zeitwerk::Loader:0x000055c520803ed8
  @autoloads=
   {"/app/engines/perks_by/spec/internal/app/graphql/test_schema.rb"=>[Object, "TestSchema"],
    "/app/engines/perks_by/app/graphql/perks_by/query_interface.rb"=>[PerksBy, "QueryInterface"],
    "/app/engines/perks_by/app/graphql/perks_by/types.rb"=>[PerksBy, "Types"],
    "/app/engines/perks_by/app/models/perks_by/city_perk.rb"=>[PerksBy, "CityPerk"],
    "/app/engines/perks_by/app/models/perks_by/perk.rb"=>[PerksBy, "Perk"],
    "/app/engines/perks_by/app/models/perks_by/perk_type.rb"=>[PerksBy, "PerkType"],
    "/app/engines/perks_by/app/policies/perks_by/perk_policy.rb"=>[PerksBy, "PerkPolicy"],
    "/app/engines/perks_by/app/queries/perks_by/perks"=>[PerksBy, "Perks"]
     
    ...

    @lazy_subdirs=
   {"PerksBy::Types"=>["/app/engines/perks_by/app/graphql/perks_by/types"],

So, the dir with the file appears in the lazy_subdirs.

Also logs:

Zeitwerk@rails.main: autoload set for TestSchema, to be loaded from /app/engines/perks_by/spec/internal/app/graphql/test_schema.rb
Zeitwerk@rails.main: autoload set for PerksBy::Types, to be autovivified from /app/engines/perks_by/app/graphql/perks_by/types
Zeitwerk@rails.main: autoload set for PerksBy::QueryInterface, to be loaded from /app/engines/perks_by/app/graphql/perks_by/query_interface.rb
Zeitwerk@rails.main: autoload set for PerksBy::Types, to be loaded from /app/engines/perks_by/app/graphql/perks_by/types.rb

# nothing for /app/engines/perks_by/app/graphql/perks_by/types/perk.rb

[1] pry> PerksBy::Types::Perk
Zeitwerk@rails.main: constant PerksBy::Types loaded from file /app/engines/perks_by/app/graphql/perks_by/types.rb
NameError: uninitialized constant PerksBy::Types::Perk

Without pry-byebug all worked fine.

In my case (@bibendi could you check please, too), the failure only occurs only in the debugging context (i.e. within a Pry session after hitting a binding.pry). The presence of require "pry-byebug" itself doesn't break anything.

@palkan
Copy link

palkan commented Apr 4, 2019

@fxn Well, I found the cause: byebug stops the main execution thread thus making TracePoint no-op:

And that's a bad news( byebug is a default Rails debugger.

One possible solution is to activate the TracePoint in its own thread (though adding this just to make one specific debugger happy sounds strange).

@fxn
Copy link
Owner

fxn commented Apr 4, 2019

I have some stuff with higher priority in Zeitwerk, but will eventually get to this.

I’ll try also to understand if this is an issue that should have to be opened in byebug, since Zeitwerk is using ordinary Ruby and it is the debugger the one changing part of that.

Bootsnap for example implemented a couple of things to comply with edgy but standard Ruby semantics Zeitwerk relies on.

Let’s see!

@marshall-lee
Copy link

Hi everyone! If you're still interested I made a fix for byebug + zeitwerk compatibility. deivid-rodriguez/byebug#847

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants