Ambiguity in Ruby class name resolution












3















I recently did some code refactoring in a Rails codebase in which I converted some code that defined some classes like this (class bodies elided):



foo/user_bar.rb:



module Foo
class UserBar; end
end


foo/sub_user_bar.rb:



module Foo
class SubUserBar < UserBar; end
end


...to:



In foo/bar/user.rb:



module Foo
module Bar
class User; end
end
end


In foo/bar/sub_user.rb:



module Foo
module Bar
class SubUser < User; end
end
end


This introduced a subtle problem in that there was already an existing top-level class called User (a Rails model), and SubUser was being derived from that, not from User in the same module. I'm guess that this is because the order that Rails loads classes is unpredictable...?



Anyway, I found that I could disambiguate by declaring the SubUser class like this:



class SubUser < self::User


...which seems to work, although I couldn't find any examples of it in a modest amount of searching. It does look a little weird, though. And now I'm concerned that I really ought to be doing this for every class in my module, just in case a top-level class with the same name is ever introduced.



There are two styles of in-module class declarations throughout my company's codebase:



class A::B::Foo; end


And:



module A; module B; class Foo; end; end; end


I've always preferred the latter method since it allows for access to other names in the module without fully-qualified names, but now I've found that there's potentially a trap when I use it. So what's the best practice here?




  • Don't declare classes within a module; always use fully qualified names (class A::B::C::Foo < A::B::C::Bar)

  • Declare classes in a module but always fully qualify superclass names (module A; module B; module C; class Foo < A::B::C::Bar)

  • Declare classes in a module and use unqualified names but always use self:: when extending a class in the same module

  • Declare classes in a module and use unqualified names but stay aware of possible name collisions in the top-level namespace (seems risky)


Or do Ruby and/or Rails offer some other, cleaner way to resolve the issue?










share|improve this question



























    3















    I recently did some code refactoring in a Rails codebase in which I converted some code that defined some classes like this (class bodies elided):



    foo/user_bar.rb:



    module Foo
    class UserBar; end
    end


    foo/sub_user_bar.rb:



    module Foo
    class SubUserBar < UserBar; end
    end


    ...to:



    In foo/bar/user.rb:



    module Foo
    module Bar
    class User; end
    end
    end


    In foo/bar/sub_user.rb:



    module Foo
    module Bar
    class SubUser < User; end
    end
    end


    This introduced a subtle problem in that there was already an existing top-level class called User (a Rails model), and SubUser was being derived from that, not from User in the same module. I'm guess that this is because the order that Rails loads classes is unpredictable...?



    Anyway, I found that I could disambiguate by declaring the SubUser class like this:



    class SubUser < self::User


    ...which seems to work, although I couldn't find any examples of it in a modest amount of searching. It does look a little weird, though. And now I'm concerned that I really ought to be doing this for every class in my module, just in case a top-level class with the same name is ever introduced.



    There are two styles of in-module class declarations throughout my company's codebase:



    class A::B::Foo; end


    And:



    module A; module B; class Foo; end; end; end


    I've always preferred the latter method since it allows for access to other names in the module without fully-qualified names, but now I've found that there's potentially a trap when I use it. So what's the best practice here?




    • Don't declare classes within a module; always use fully qualified names (class A::B::C::Foo < A::B::C::Bar)

    • Declare classes in a module but always fully qualify superclass names (module A; module B; module C; class Foo < A::B::C::Bar)

    • Declare classes in a module and use unqualified names but always use self:: when extending a class in the same module

    • Declare classes in a module and use unqualified names but stay aware of possible name collisions in the top-level namespace (seems risky)


    Or do Ruby and/or Rails offer some other, cleaner way to resolve the issue?










    share|improve this question

























      3












      3








      3


      0






      I recently did some code refactoring in a Rails codebase in which I converted some code that defined some classes like this (class bodies elided):



      foo/user_bar.rb:



      module Foo
      class UserBar; end
      end


      foo/sub_user_bar.rb:



      module Foo
      class SubUserBar < UserBar; end
      end


      ...to:



      In foo/bar/user.rb:



      module Foo
      module Bar
      class User; end
      end
      end


      In foo/bar/sub_user.rb:



      module Foo
      module Bar
      class SubUser < User; end
      end
      end


      This introduced a subtle problem in that there was already an existing top-level class called User (a Rails model), and SubUser was being derived from that, not from User in the same module. I'm guess that this is because the order that Rails loads classes is unpredictable...?



      Anyway, I found that I could disambiguate by declaring the SubUser class like this:



      class SubUser < self::User


      ...which seems to work, although I couldn't find any examples of it in a modest amount of searching. It does look a little weird, though. And now I'm concerned that I really ought to be doing this for every class in my module, just in case a top-level class with the same name is ever introduced.



      There are two styles of in-module class declarations throughout my company's codebase:



      class A::B::Foo; end


      And:



      module A; module B; class Foo; end; end; end


      I've always preferred the latter method since it allows for access to other names in the module without fully-qualified names, but now I've found that there's potentially a trap when I use it. So what's the best practice here?




      • Don't declare classes within a module; always use fully qualified names (class A::B::C::Foo < A::B::C::Bar)

      • Declare classes in a module but always fully qualify superclass names (module A; module B; module C; class Foo < A::B::C::Bar)

      • Declare classes in a module and use unqualified names but always use self:: when extending a class in the same module

      • Declare classes in a module and use unqualified names but stay aware of possible name collisions in the top-level namespace (seems risky)


      Or do Ruby and/or Rails offer some other, cleaner way to resolve the issue?










      share|improve this question














      I recently did some code refactoring in a Rails codebase in which I converted some code that defined some classes like this (class bodies elided):



      foo/user_bar.rb:



      module Foo
      class UserBar; end
      end


      foo/sub_user_bar.rb:



      module Foo
      class SubUserBar < UserBar; end
      end


      ...to:



      In foo/bar/user.rb:



      module Foo
      module Bar
      class User; end
      end
      end


      In foo/bar/sub_user.rb:



      module Foo
      module Bar
      class SubUser < User; end
      end
      end


      This introduced a subtle problem in that there was already an existing top-level class called User (a Rails model), and SubUser was being derived from that, not from User in the same module. I'm guess that this is because the order that Rails loads classes is unpredictable...?



      Anyway, I found that I could disambiguate by declaring the SubUser class like this:



      class SubUser < self::User


      ...which seems to work, although I couldn't find any examples of it in a modest amount of searching. It does look a little weird, though. And now I'm concerned that I really ought to be doing this for every class in my module, just in case a top-level class with the same name is ever introduced.



      There are two styles of in-module class declarations throughout my company's codebase:



      class A::B::Foo; end


      And:



      module A; module B; class Foo; end; end; end


      I've always preferred the latter method since it allows for access to other names in the module without fully-qualified names, but now I've found that there's potentially a trap when I use it. So what's the best practice here?




      • Don't declare classes within a module; always use fully qualified names (class A::B::C::Foo < A::B::C::Bar)

      • Declare classes in a module but always fully qualify superclass names (module A; module B; module C; class Foo < A::B::C::Bar)

      • Declare classes in a module and use unqualified names but always use self:: when extending a class in the same module

      • Declare classes in a module and use unqualified names but stay aware of possible name collisions in the top-level namespace (seems risky)


      Or do Ruby and/or Rails offer some other, cleaner way to resolve the issue?







      ruby-on-rails ruby






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Jan 18 at 20:04









      SeanSean

      23.4k36588




      23.4k36588
























          2 Answers
          2






          active

          oldest

          votes


















          2














          Generally where there's ambiguity you specify full namespace paths:



          module Foo
          module Bar
          class SubUser < Foo::Bar::User; end
          end
          end


          That might seem verbose, but it's also specific and unambiguous.



          Where you want to refer to literal top-level User you'd specify ::User.






          share|improve this answer































            0














            Modules are identified by constants.1 The resolution of module look-ups is therefore determined by the procedure for looking up constant references. According to "The Ruby Programming Language", by David Flanagan and Yukihero Matsumoto, 1st Ed. 2008 (p. 261-262), constant look-ups are performed in the following order, where mod is the innermost module that encloses the reference to the constant:





            • mod.

            • the next enclosing module, continuing until there are no more enclosing modules. (Top-level/global constants are not considered at this step). The class method Module::nesting returns an array of modules that are so searched, in the order in which they are searched.

            • the elements of mod.ancestors, in index order (i.e., the inheritance hierarchy).

            • top-level constant definitions.

            • the value returned by the method Module#const_missing, with mod being the receiver and the constant expressed as a symbol being the argument, provided the method has been defined.


            Let's see what we may learn by inserting puts Module.nesting.inspect and puts ancestors statements into the code.



            module Foo
            class UserBar
            puts "nesting for UserBar=#{Module.nesting.inspect}"
            puts "#{self}.ancestors=#{ancestors}"
            end
            end
            # nesting for UserBar=[Foo::UserBar, Foo]
            # Foo::UserBar.ancestors=[Foo::UserBar, Object, Kernel,
            # BasicObject]

            module Foo
            class SubUserBar < UserBar
            puts "nesting for SubUserBar=#{Module.nesting.inspect}"
            puts "#{self}.ancestors=#{ancestors}"
            end
            end
            # nesting for SubUserBar=[Foo::SubUserBar, Foo]
            # Foo::SubUserBar.ancestors=[Foo::SubUserBar,
            # Foo::UserBar, Object, Kernel, BasicObject]





            module Foo
            module Bar
            class User
            puts "nesting for User=#{Module.nesting.inspect}"
            puts "#{self}.ancestors=#{ancestors}"
            end
            end
            end
            # nesting for User=[Foo::Bar::User, Foo::Bar, Foo]
            # Foo::Bar::User.ancestors=[Foo::Bar::User, Object, Kernel,
            # BasicObject]

            module Foo
            module Bar
            class SubUser < User
            puts "nesting for SubBar=#{Module.nesting.inspect}"
            puts "#{self}.ancestors=#{ancestors}"
            end
            end
            end
            # nesting for SubBar=[Foo::Bar::SubUser, Foo::Bar, Foo]
            # Foo::Bar::SubUser.ancestors=[Foo::Bar::SubUser,
            # Foo::Bar::User, Object, Kernel, BasicObject]


            This tells us that if there is a class User that is not contained within Foo (as in Rails), that class would the subject of references to User in the classes Foo::UserBar and Foo::SubUserBar, but not in Foo::Bar::User or Foo::Bar::SubUser. This understanding should help in organising modules to avoid namespace problems.



            1 As classes are modules, whenever I reference "module" below I am referring to classes as well as modules that are not classes.






            share|improve this answer

























              Your Answer






              StackExchange.ifUsing("editor", function () {
              StackExchange.using("externalEditor", function () {
              StackExchange.using("snippets", function () {
              StackExchange.snippets.init();
              });
              });
              }, "code-snippets");

              StackExchange.ready(function() {
              var channelOptions = {
              tags: "".split(" "),
              id: "1"
              };
              initTagRenderer("".split(" "), "".split(" "), channelOptions);

              StackExchange.using("externalEditor", function() {
              // Have to fire editor after snippets, if snippets enabled
              if (StackExchange.settings.snippets.snippetsEnabled) {
              StackExchange.using("snippets", function() {
              createEditor();
              });
              }
              else {
              createEditor();
              }
              });

              function createEditor() {
              StackExchange.prepareEditor({
              heartbeatType: 'answer',
              autoActivateHeartbeat: false,
              convertImagesToLinks: true,
              noModals: true,
              showLowRepImageUploadWarning: true,
              reputationToPostImages: 10,
              bindNavPrevention: true,
              postfix: "",
              imageUploader: {
              brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
              contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
              allowUrls: true
              },
              onDemand: true,
              discardSelector: ".discard-answer"
              ,immediatelyShowMarkdownHelp:true
              });


              }
              });














              draft saved

              draft discarded


















              StackExchange.ready(
              function () {
              StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54260744%2fambiguity-in-ruby-class-name-resolution%23new-answer', 'question_page');
              }
              );

              Post as a guest















              Required, but never shown

























              2 Answers
              2






              active

              oldest

              votes








              2 Answers
              2






              active

              oldest

              votes









              active

              oldest

              votes






              active

              oldest

              votes









              2














              Generally where there's ambiguity you specify full namespace paths:



              module Foo
              module Bar
              class SubUser < Foo::Bar::User; end
              end
              end


              That might seem verbose, but it's also specific and unambiguous.



              Where you want to refer to literal top-level User you'd specify ::User.






              share|improve this answer




























                2














                Generally where there's ambiguity you specify full namespace paths:



                module Foo
                module Bar
                class SubUser < Foo::Bar::User; end
                end
                end


                That might seem verbose, but it's also specific and unambiguous.



                Where you want to refer to literal top-level User you'd specify ::User.






                share|improve this answer


























                  2












                  2








                  2







                  Generally where there's ambiguity you specify full namespace paths:



                  module Foo
                  module Bar
                  class SubUser < Foo::Bar::User; end
                  end
                  end


                  That might seem verbose, but it's also specific and unambiguous.



                  Where you want to refer to literal top-level User you'd specify ::User.






                  share|improve this answer













                  Generally where there's ambiguity you specify full namespace paths:



                  module Foo
                  module Bar
                  class SubUser < Foo::Bar::User; end
                  end
                  end


                  That might seem verbose, but it's also specific and unambiguous.



                  Where you want to refer to literal top-level User you'd specify ::User.







                  share|improve this answer












                  share|improve this answer



                  share|improve this answer










                  answered Jan 18 at 20:48









                  tadmantadman

                  153k18174208




                  153k18174208

























                      0














                      Modules are identified by constants.1 The resolution of module look-ups is therefore determined by the procedure for looking up constant references. According to "The Ruby Programming Language", by David Flanagan and Yukihero Matsumoto, 1st Ed. 2008 (p. 261-262), constant look-ups are performed in the following order, where mod is the innermost module that encloses the reference to the constant:





                      • mod.

                      • the next enclosing module, continuing until there are no more enclosing modules. (Top-level/global constants are not considered at this step). The class method Module::nesting returns an array of modules that are so searched, in the order in which they are searched.

                      • the elements of mod.ancestors, in index order (i.e., the inheritance hierarchy).

                      • top-level constant definitions.

                      • the value returned by the method Module#const_missing, with mod being the receiver and the constant expressed as a symbol being the argument, provided the method has been defined.


                      Let's see what we may learn by inserting puts Module.nesting.inspect and puts ancestors statements into the code.



                      module Foo
                      class UserBar
                      puts "nesting for UserBar=#{Module.nesting.inspect}"
                      puts "#{self}.ancestors=#{ancestors}"
                      end
                      end
                      # nesting for UserBar=[Foo::UserBar, Foo]
                      # Foo::UserBar.ancestors=[Foo::UserBar, Object, Kernel,
                      # BasicObject]

                      module Foo
                      class SubUserBar < UserBar
                      puts "nesting for SubUserBar=#{Module.nesting.inspect}"
                      puts "#{self}.ancestors=#{ancestors}"
                      end
                      end
                      # nesting for SubUserBar=[Foo::SubUserBar, Foo]
                      # Foo::SubUserBar.ancestors=[Foo::SubUserBar,
                      # Foo::UserBar, Object, Kernel, BasicObject]





                      module Foo
                      module Bar
                      class User
                      puts "nesting for User=#{Module.nesting.inspect}"
                      puts "#{self}.ancestors=#{ancestors}"
                      end
                      end
                      end
                      # nesting for User=[Foo::Bar::User, Foo::Bar, Foo]
                      # Foo::Bar::User.ancestors=[Foo::Bar::User, Object, Kernel,
                      # BasicObject]

                      module Foo
                      module Bar
                      class SubUser < User
                      puts "nesting for SubBar=#{Module.nesting.inspect}"
                      puts "#{self}.ancestors=#{ancestors}"
                      end
                      end
                      end
                      # nesting for SubBar=[Foo::Bar::SubUser, Foo::Bar, Foo]
                      # Foo::Bar::SubUser.ancestors=[Foo::Bar::SubUser,
                      # Foo::Bar::User, Object, Kernel, BasicObject]


                      This tells us that if there is a class User that is not contained within Foo (as in Rails), that class would the subject of references to User in the classes Foo::UserBar and Foo::SubUserBar, but not in Foo::Bar::User or Foo::Bar::SubUser. This understanding should help in organising modules to avoid namespace problems.



                      1 As classes are modules, whenever I reference "module" below I am referring to classes as well as modules that are not classes.






                      share|improve this answer






























                        0














                        Modules are identified by constants.1 The resolution of module look-ups is therefore determined by the procedure for looking up constant references. According to "The Ruby Programming Language", by David Flanagan and Yukihero Matsumoto, 1st Ed. 2008 (p. 261-262), constant look-ups are performed in the following order, where mod is the innermost module that encloses the reference to the constant:





                        • mod.

                        • the next enclosing module, continuing until there are no more enclosing modules. (Top-level/global constants are not considered at this step). The class method Module::nesting returns an array of modules that are so searched, in the order in which they are searched.

                        • the elements of mod.ancestors, in index order (i.e., the inheritance hierarchy).

                        • top-level constant definitions.

                        • the value returned by the method Module#const_missing, with mod being the receiver and the constant expressed as a symbol being the argument, provided the method has been defined.


                        Let's see what we may learn by inserting puts Module.nesting.inspect and puts ancestors statements into the code.



                        module Foo
                        class UserBar
                        puts "nesting for UserBar=#{Module.nesting.inspect}"
                        puts "#{self}.ancestors=#{ancestors}"
                        end
                        end
                        # nesting for UserBar=[Foo::UserBar, Foo]
                        # Foo::UserBar.ancestors=[Foo::UserBar, Object, Kernel,
                        # BasicObject]

                        module Foo
                        class SubUserBar < UserBar
                        puts "nesting for SubUserBar=#{Module.nesting.inspect}"
                        puts "#{self}.ancestors=#{ancestors}"
                        end
                        end
                        # nesting for SubUserBar=[Foo::SubUserBar, Foo]
                        # Foo::SubUserBar.ancestors=[Foo::SubUserBar,
                        # Foo::UserBar, Object, Kernel, BasicObject]





                        module Foo
                        module Bar
                        class User
                        puts "nesting for User=#{Module.nesting.inspect}"
                        puts "#{self}.ancestors=#{ancestors}"
                        end
                        end
                        end
                        # nesting for User=[Foo::Bar::User, Foo::Bar, Foo]
                        # Foo::Bar::User.ancestors=[Foo::Bar::User, Object, Kernel,
                        # BasicObject]

                        module Foo
                        module Bar
                        class SubUser < User
                        puts "nesting for SubBar=#{Module.nesting.inspect}"
                        puts "#{self}.ancestors=#{ancestors}"
                        end
                        end
                        end
                        # nesting for SubBar=[Foo::Bar::SubUser, Foo::Bar, Foo]
                        # Foo::Bar::SubUser.ancestors=[Foo::Bar::SubUser,
                        # Foo::Bar::User, Object, Kernel, BasicObject]


                        This tells us that if there is a class User that is not contained within Foo (as in Rails), that class would the subject of references to User in the classes Foo::UserBar and Foo::SubUserBar, but not in Foo::Bar::User or Foo::Bar::SubUser. This understanding should help in organising modules to avoid namespace problems.



                        1 As classes are modules, whenever I reference "module" below I am referring to classes as well as modules that are not classes.






                        share|improve this answer




























                          0












                          0








                          0







                          Modules are identified by constants.1 The resolution of module look-ups is therefore determined by the procedure for looking up constant references. According to "The Ruby Programming Language", by David Flanagan and Yukihero Matsumoto, 1st Ed. 2008 (p. 261-262), constant look-ups are performed in the following order, where mod is the innermost module that encloses the reference to the constant:





                          • mod.

                          • the next enclosing module, continuing until there are no more enclosing modules. (Top-level/global constants are not considered at this step). The class method Module::nesting returns an array of modules that are so searched, in the order in which they are searched.

                          • the elements of mod.ancestors, in index order (i.e., the inheritance hierarchy).

                          • top-level constant definitions.

                          • the value returned by the method Module#const_missing, with mod being the receiver and the constant expressed as a symbol being the argument, provided the method has been defined.


                          Let's see what we may learn by inserting puts Module.nesting.inspect and puts ancestors statements into the code.



                          module Foo
                          class UserBar
                          puts "nesting for UserBar=#{Module.nesting.inspect}"
                          puts "#{self}.ancestors=#{ancestors}"
                          end
                          end
                          # nesting for UserBar=[Foo::UserBar, Foo]
                          # Foo::UserBar.ancestors=[Foo::UserBar, Object, Kernel,
                          # BasicObject]

                          module Foo
                          class SubUserBar < UserBar
                          puts "nesting for SubUserBar=#{Module.nesting.inspect}"
                          puts "#{self}.ancestors=#{ancestors}"
                          end
                          end
                          # nesting for SubUserBar=[Foo::SubUserBar, Foo]
                          # Foo::SubUserBar.ancestors=[Foo::SubUserBar,
                          # Foo::UserBar, Object, Kernel, BasicObject]





                          module Foo
                          module Bar
                          class User
                          puts "nesting for User=#{Module.nesting.inspect}"
                          puts "#{self}.ancestors=#{ancestors}"
                          end
                          end
                          end
                          # nesting for User=[Foo::Bar::User, Foo::Bar, Foo]
                          # Foo::Bar::User.ancestors=[Foo::Bar::User, Object, Kernel,
                          # BasicObject]

                          module Foo
                          module Bar
                          class SubUser < User
                          puts "nesting for SubBar=#{Module.nesting.inspect}"
                          puts "#{self}.ancestors=#{ancestors}"
                          end
                          end
                          end
                          # nesting for SubBar=[Foo::Bar::SubUser, Foo::Bar, Foo]
                          # Foo::Bar::SubUser.ancestors=[Foo::Bar::SubUser,
                          # Foo::Bar::User, Object, Kernel, BasicObject]


                          This tells us that if there is a class User that is not contained within Foo (as in Rails), that class would the subject of references to User in the classes Foo::UserBar and Foo::SubUserBar, but not in Foo::Bar::User or Foo::Bar::SubUser. This understanding should help in organising modules to avoid namespace problems.



                          1 As classes are modules, whenever I reference "module" below I am referring to classes as well as modules that are not classes.






                          share|improve this answer















                          Modules are identified by constants.1 The resolution of module look-ups is therefore determined by the procedure for looking up constant references. According to "The Ruby Programming Language", by David Flanagan and Yukihero Matsumoto, 1st Ed. 2008 (p. 261-262), constant look-ups are performed in the following order, where mod is the innermost module that encloses the reference to the constant:





                          • mod.

                          • the next enclosing module, continuing until there are no more enclosing modules. (Top-level/global constants are not considered at this step). The class method Module::nesting returns an array of modules that are so searched, in the order in which they are searched.

                          • the elements of mod.ancestors, in index order (i.e., the inheritance hierarchy).

                          • top-level constant definitions.

                          • the value returned by the method Module#const_missing, with mod being the receiver and the constant expressed as a symbol being the argument, provided the method has been defined.


                          Let's see what we may learn by inserting puts Module.nesting.inspect and puts ancestors statements into the code.



                          module Foo
                          class UserBar
                          puts "nesting for UserBar=#{Module.nesting.inspect}"
                          puts "#{self}.ancestors=#{ancestors}"
                          end
                          end
                          # nesting for UserBar=[Foo::UserBar, Foo]
                          # Foo::UserBar.ancestors=[Foo::UserBar, Object, Kernel,
                          # BasicObject]

                          module Foo
                          class SubUserBar < UserBar
                          puts "nesting for SubUserBar=#{Module.nesting.inspect}"
                          puts "#{self}.ancestors=#{ancestors}"
                          end
                          end
                          # nesting for SubUserBar=[Foo::SubUserBar, Foo]
                          # Foo::SubUserBar.ancestors=[Foo::SubUserBar,
                          # Foo::UserBar, Object, Kernel, BasicObject]





                          module Foo
                          module Bar
                          class User
                          puts "nesting for User=#{Module.nesting.inspect}"
                          puts "#{self}.ancestors=#{ancestors}"
                          end
                          end
                          end
                          # nesting for User=[Foo::Bar::User, Foo::Bar, Foo]
                          # Foo::Bar::User.ancestors=[Foo::Bar::User, Object, Kernel,
                          # BasicObject]

                          module Foo
                          module Bar
                          class SubUser < User
                          puts "nesting for SubBar=#{Module.nesting.inspect}"
                          puts "#{self}.ancestors=#{ancestors}"
                          end
                          end
                          end
                          # nesting for SubBar=[Foo::Bar::SubUser, Foo::Bar, Foo]
                          # Foo::Bar::SubUser.ancestors=[Foo::Bar::SubUser,
                          # Foo::Bar::User, Object, Kernel, BasicObject]


                          This tells us that if there is a class User that is not contained within Foo (as in Rails), that class would the subject of references to User in the classes Foo::UserBar and Foo::SubUserBar, but not in Foo::Bar::User or Foo::Bar::SubUser. This understanding should help in organising modules to avoid namespace problems.



                          1 As classes are modules, whenever I reference "module" below I am referring to classes as well as modules that are not classes.







                          share|improve this answer














                          share|improve this answer



                          share|improve this answer








                          edited Jan 18 at 22:39

























                          answered Jan 18 at 22:33









                          Cary SwovelandCary Swoveland

                          68.7k54065




                          68.7k54065






























                              draft saved

                              draft discarded




















































                              Thanks for contributing an answer to Stack Overflow!


                              • Please be sure to answer the question. Provide details and share your research!

                              But avoid



                              • Asking for help, clarification, or responding to other answers.

                              • Making statements based on opinion; back them up with references or personal experience.


                              To learn more, see our tips on writing great answers.




                              draft saved


                              draft discarded














                              StackExchange.ready(
                              function () {
                              StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54260744%2fambiguity-in-ruby-class-name-resolution%23new-answer', 'question_page');
                              }
                              );

                              Post as a guest















                              Required, but never shown





















































                              Required, but never shown














                              Required, but never shown












                              Required, but never shown







                              Required, but never shown

































                              Required, but never shown














                              Required, but never shown












                              Required, but never shown







                              Required, but never shown







                              Popular posts from this blog

                              Callistus III

                              Plistias Cous

                              Index Sanctorum