简体   繁体   中英

Do I need to create folder hierarchy for nested module class in Rails

I have a scenario where I just need to inherite the classes in my subclass, there is not single line of code. Just due to STI I need to create it.

Ex:

|-- 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

Question and scenario:

I have lots of files like Ax1 which needs hierarchy but that doesn't contains anything except inheritance. So one way is to create all (unnecessary :( ) folders and put the file inside it as per Rails conventions.

And as I have many files so I want it to put in single file with all classes with inheritance (but as per Rails conventions, single class should be in single file with same name).

Is there any way to achieve this?

And as I have many files so I want it to put in single file with all classes with inheritance

You can't do this without breaking "convention over configuration". But if you're willing to violate that, it's quite easy. Just put all your classes in one file, say, app/models/my_classes.rb and then just make sure that the file is loaded before you need any class from it.

One way of doing this is create an initializer

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

Rails lazy loads your code, so a class or module definition is not read until it is needed. It will look for the top-level constant first. So if you define A::A1::Special::A2::Ax1 it first checks for a.rb at the top level, before it moves on to a1.rb . If it finds a definition like this class A::A1::Special::A2::Ax1; end class A::A1::Special::A2::Ax1; end in a.rb it will raise a circular dependency because it will keep looking for a definition for that top level A first, going back to a.rb over and over again. And if your classes are defined in some randomly named file, they'll never be found. Just make sure you're putting them in files with names that make sense, and you're declaring each module separately.

This should work:

app/models/a.rb

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

This will not

app/models/a.rb

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

And neither will this

app/models/inherited_classes.rb

class A
  class A1 < A
    class Special < A1
      class A2 < Special
        class Ax1 < A2
      end
    end
  end
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