【问题标题】:Do I need to create folder hierarchy for nested module class in Rails我是否需要为 Rails 中的嵌套模块类创建文件夹层次结构
【发布时间】:2017-08-02 06:59:52
【问题描述】:

我有一个场景,我只需要继承我的子类中的类,没有单行代码。只是由于 STI,我需要创建它。

例如:

|-- app
|   |-- models
|   |   |-- a
|   |   |   |-- a1
|   |   |   |   |-- special
|   |   |   |   |   |-- a2
|   |   |   |   |   |   *-- ax1.rb #(A::A1::Special::A2::Ax1 < A::A1::A2::Ax)
|   |   |   |   |-- a2
|   |   |   |   |   *-- ax.rb
|   |   |-- b
|   |   |   |-- b1
|   |   |   |   |-- b2
|   |   |   |   |   *-- bx.rb #(B::B1::B2::Bx)
|   |   |-- c
|   |   `-- concerns

问题和场景:

我有很多像Ax1 这样的文件,它们需要层次结构,但除了继承之外什么都不包含。因此,一种方法是创建所有(不必要的 :( ) 文件夹并按照 Rails 约定将文件放入其中。

由于我有很多文件,所以我希望它与所有具有继承的类一起放入单个文件中(但根据 Rails 约定,单个类应该放在同名的单个文件中)。

有什么办法可以做到吗?

【问题讨论】:

    标签: ruby-on-rails ruby-on-rails-4 inheritance convention-over-configur


    【解决方案1】:

    由于我有很多文件,所以我希望它与所有具有继承的类放在一个文件中

    如果不打破“约定优于配置”,您就无法做到这一点。但是,如果您愿意违反这一点,那很容易。只需将所有类放在一个文件中,例如app/models/my_classes.rb,然后确保在您需要任何类之前加载该文件。

    一种方法是创建一个初始化器

    # config/initializers/load_common_classes.rb
    require 'my_classes'
    

    【讨论】:

      【解决方案2】:

      Rails 会延迟加载您的代码,因此在需要之前不会读取类或模块定义。它将首先查找*常量。因此,如果您定义A::A1::Special::A2::Ax1,它首先会在顶层检查a.rb,然后再转到a1.rb。如果它在a.rb 中找到类似class A::A1::Special::A2::Ax1; end 的定义,它将引发循环依赖,因为它将首先继续寻找*A 的定义,然后一遍又一遍地返回a.rb。如果你的类是在一些随机命名的文件中定义的,它们将永远不会被发现。只需确保将它们放入名称合理的文件中,并且分别声明每个模块。

      这应该可行:

      app/models/a.rb

      class A
        class A1 < A
          class Special < A1
            class A2 < Special
              class Ax1 < A2
            end
          end
        end
      end
      

      这不会

      app/models/a.rb

      class A::A1::Special::A2::Ax1
      end
      

      这个也不会

      app/models/inherited_classes.rb

      class A
        class A1 < A
          class Special < A1
            class A2 < Special
              class Ax1 < A2
            end
          end
        end
      end
      

      【讨论】: