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

YY::XX always references XX if XX was defined #6931

Closed
ayamomiji opened this Issue Jul 2, 2012 · 8 comments

Comments

Projects
None yet
5 participants
@ayamomiji
Contributor

ayamomiji commented Jul 2, 2012

# app/models/auth.rb
class Auth < ActiveRecord::Base; end
# app/models/auth/twitter.rb
class Auth::Twitter < Auth; end

# in console
>> Auth::Twitter
(rib-rails):1: warning: toplevel constant Twitter referenced by Auth::Twitter
=> Twitter # expect to be Auth::Twitter that defines in app/models/auth/twitter.rb

another example:

# app/models/user.rb
class User < ActiveRecord::Base; end

# in console
>> User::User::User::User::User::User::User::User::User::User
(rib-rails):1: warning: toplevel constant User referenced by User::User
(rib-rails):1: warning: toplevel constant User referenced by User::User
(rib-rails):1: warning: toplevel constant User referenced by User::User
(rib-rails):1: warning: toplevel constant User referenced by User::User
(rib-rails):1: warning: toplevel constant User referenced by User::User
(rib-rails):1: warning: toplevel constant User referenced by User::User
(rib-rails):1: warning: toplevel constant User referenced by User::User
(rib-rails):1: warning: toplevel constant User referenced by User::User
(rib-rails):1: warning: toplevel constant User referenced by User::User
=> User(...)
@fxn

This comment has been minimized.

Member

fxn commented Jul 2, 2012

The second example is just the way Ruby works:

fxn@yeager:~ $ ruby -e 'class A; end; A::A'
-e:1: warning: toplevel constant A referenced by A::A

That happens because the rightmost A constant is found in one of the ancestors of the leftmost A, namely Object. Note that would not happen if A was a module, since Object would not be among its ancestors.

The first example is more interesting. Constant autoloading in Rails is based on const_missing. But for the same reason User::User works, the top-level Twitter constant is found via the qualified name Auth::Twitter if auth/twitter.rb has not yet been loaded. Therefore, const_missing is not even triggered.

@ghost ghost assigned fxn Jul 2, 2012

@fxn

This comment has been minimized.

Member

fxn commented Jul 3, 2012

Hi @ayamomiji do you think we can close this issue?

@ayamomiji

This comment has been minimized.

Contributor

ayamomiji commented Jul 3, 2012

Hi,
Thanks for reply.
I just added require_dependency 'auth/twitter' to every files that references Auth::Twitter to avoid this problem, and it works fine now.

@ayamomiji ayamomiji closed this Jul 3, 2012

@fxn

This comment has been minimized.

Member

fxn commented Jul 3, 2012

Excellent, thanks!

@petRUShka

This comment has been minimized.

petRUShka commented Jun 19, 2013

Is it a good idea to advice people to add require_dependency 'auth/twitter' in each file that use Auth::Twitter? It isn't convenient at least. And it isn't easy to find the reason of warning: toplevel constant Twitter referenced by like warnings (and hence errors off course) without extensive googling and stackoverflowing...

Is it possible for Rails to try to require auth/twitter' in case of such warning?

@fxn

This comment has been minimized.

Member

fxn commented Jun 19, 2013

The warning is issued by the interpreter, Rails does not see it.

@gucki

This comment has been minimized.

gucki commented Sep 23, 2015

I created an issue von ruby-lang to remove the top-level constant lookup fallback. This should resolve the issue in a clean way: https://bugs.ruby-lang.org/issues/11547

betesh added a commit to betesh/rspec-rails that referenced this issue Jul 5, 2016

Rescue TypeError if a top-level class named Behavior exists
If your application defines a top-level class named Behavior, loading
rspec/rails/example/request_example_group.rb with Rails 3.2.22.1
results in a compiler warning:

`warning: toplevel constant Behavior referenced by ActionDispatch::IntegrationTest::Behavior`

This warning is the result of the situation descibed in rails/rails#6931,
i.e. Rails auto-load magic concludes that the constant named Behavior is already
defined, and tries to use it instead of attempting to auto-load a properly namespaced one.

The result is a TypeError, which can safely be swallowed.
@eugeneius

This comment has been minimized.

Member

eugeneius commented Jan 14, 2017

As of ruby/ruby@44a2576, this is no longer an issue!

The commit message says it's "experimental", but hopefully it will be released in Ruby 2.5.

Thank you for taking the time to report it @gucki 👏

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment