简体   繁体   中英

Nesting class in module vs using module as part of class name

Similar to module and class with the same name in Rails project , but I'm trying to understand why putting it all on one line works but using separate lines does not.

Working with inviting new users to an account. My user model has the minimum validation, and I use subclasses with additional behavior. This is similar to service objects, but subclasses are cleaner than services most of the time because they are all kept in the /app/models folder and is easier to maintain.

I have app/models/user/as_invitation.rb . When it looks like the following, it works fine:

class ::User::AsInvitation < ::User
  # ...
end

But when I have this, it does not work: "User is not a module".

module User
  class AsInvitation < ::User
    # ...
  end
end

My suspicion is that Ruby uses the same namespace for modules/classes, and since I already have a User class (model), it collides with the User module (module vs model).

I can use the ::User::AsInvitation format and it works, but it bugs me when magic happens. As another solution, I can use the module name Users plural, but it makes more sense to me to use singular User as the namespace.

I'm trying to understand a bit under-the-hood of how Ruby/Rails implement this as well as determine if I go ahead and use ::User::AsInvitation on one line, whether I am going to find myself down a river without a paddle.

@JörgWMittag answered my question in the comments (if you want to throw this into an answer I'll accept it):

module User
end

and

class User < ActiveRecord::Base
end

both resolve to the same constant in Ruby ( User ) and thus collide, whereas:

module User
  class AsActive < ActiveRecord::Base
  end
end

and

class ::User::AsActive < ActiveRecord::Base
end

resolves to different Ruby constant ( User::AsActive vs User ). Modules and classes use the same constant namespace (may not be best word to describe it, but it makes sense to me).

The correct way, at least in Rails 6, to do this in separate files is:

# models/user.rb
class User < ApplicationRecord
end

# models/user/as_invitation.rb
class User
   class AsInvitation < User
   # ...
   end
end

# config/routes.rb
resources :users
namespace :user do
  resources :as_invitations
end

# controllers/users_controller.rb
class UsersController < ApplictionController
end

# controllers/user/as_invitations_controller.rb
class User::AsInvitationsController < UsersController
end

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM