【问题标题】:Nesting class in module vs using module as part of class name在模块中嵌套类与使用模块作为类名的一部分
【发布时间】:2016-10-14 05:25:43
【问题描述】:

类似于module and class with the same name in Rails project,但我试图理解为什么将它们全部放在一行上但使用单独的行却不行。

使用邀请新用户加入帐户。我的user 模型具有最少的验证,并且我使用具有附加行为的子类。这类似于服务对象,但大多数时候子类比服务更干净,因为它们都保存在/app/models 文件夹中并且更易于维护。

我有app/models/user/as_invitation.rb。当它看起来像以下时,它工作正常:

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

但是当我有这个时,它不起作用:“用户不是模块”。

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

我怀疑 Ruby 对模块/类使用相同的命名空间,并且由于我已经有一个 User 类(模型),它与 User 模块(模块与模型)发生冲突。

我可以使用::User::AsInvitation 格式并且它可以工作,但是当魔法发生时它会困扰我。作为另一种解决方案,我可以使用模块名称 Users 复数,但对我来说,使用单数 User 作为命名空间更有意义。

我试图了解 Ruby/Rails 是如何实现这一点的,并确定我是否继续在一行上使用 ::User::AsInvitation,我是否会发现自己陷入困境没有桨。

【问题讨论】:

  • 模块或类没有命名空间。类或模块只是一个对象,就像任何其他对象一样。
  • @JörgWMittag:我想我想知道为什么 ::User::AsInivation 可以正常工作,但是当我将它们嵌套在不同的行上时它就不起作用了?
  • module User 打开常量User 引用的模块(在当前范围内查找)如果定义了User,则首先创建带有空模块的常量User它没有定义。在您的情况下,定义了常量 User,但是 Ruby 在尝试打开模块时失败,因为 User 没有引用模块,它引用了一个类。 ::User::AsInvitation 取消引用常量User(在Object 的范围内),然后取消引用嵌套在User 引用的模块或类中的常量AsInvitation
  • 重点是:类或模块没有什么特别之处。如果您将String 分配给User 并尝试对其进行Fixnum 操作,您也会收到错误消息。在这种情况下,您将 Class 分配给 User,但您正在对其使用 Module 操作。第一种情况,你不关心是类还是模块,你只解引用一个嵌套的常量,模块和类都可以包含常量。
  • @JörgWMittag 确实,模块或类没有命名空间,但有个命名空间用于constants,按惯例用于引用它们。对吗?

标签: ruby module namespaces


【解决方案1】:

@JörgWMittag 在 cmets 中回答了我的问题(如果您想将其放入答案中,我会接受):

module User
end

class User < ActiveRecord::Base
end

两者都解析为 Ruby 中的相同常量 (User),因此发生冲突,而:

module User
  class AsActive < ActiveRecord::Base
  end
end

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

解析为不同的 Ruby 常量(User::AsActiveUser)。模块和类使用相同的常量命名空间(可能不是最好的形容词,但对我来说很有意义)。

【讨论】:

  • 你得到的错误来自告诉Ruby User 是一个模块,说module User,它不是。在第二种情况下,您只对它应用 :: 运算符,它适用于所有对象,因此 User 是什么以及它是一个类而不是一个模块是无关紧要的。
【解决方案2】:

至少在 Rails 6 中,在单独的文件中执行此操作的正确方法是:

# 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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-09-05
    • 1970-01-01
    • 2020-07-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多