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

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
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(...)
Owner

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.

@fxn fxn was assigned Jul 2, 2012

Owner

fxn commented Jul 3, 2012

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

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

Owner

fxn commented Jul 3, 2012

Excellent, thanks!

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?

Owner

fxn commented Jun 19, 2013

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

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 betesh added a commit to betesh/rspec-rails that referenced this issue Jul 5, 2016

@betesh betesh 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.
2f370dc
Contributor

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