>一个MotherClass(摘要,不能推论)
>一个SubClassA(来自MotherClass的)
>一个SubClassB(来自MotherClass的)
在Rails中声明最好的解决方案是什么?
把所有东西放在app / models /
> MotherClass < AR :: Base in app / models / mother_class.rb
> SubClassA< MotherClass在app_models / sub_class_a.rb中
> SubClassB MotherClass在app / models / sub_class_b.rb中
优点:实施起来不是很复杂
不便:模型文件夹中有一大堆混乱
2.为两个子类创建一个模块
> MotherClass < AR :: Base in app / models / mother_class.rb
> MotherModule :: SubClassA< MotherClass在app / models / mother_module / sub_class_a.rb中
> MotherModule :: SubClassB< MotherClass在app / models / mother_module / sub_class_b.rb中
优点:与解决方案1相同
不方便:命名MotherModule和MotherClass不同的名字,但他们的意思是几乎相同的事情
3.为3个类创建一个模块
> MotherModule :: Base< AR :: Base in app / models / mother_module / base.rb
> MotherModule :: SubClassA< MotherModule :: Base in app / models / mother_module / sub_class_a.rb
> MotherModule :: SubClassB< MotherModule :: Base in app / models / mother_module / sub_class_b.rb
优点:很干净
不方便:在Base中需要一些功能来覆盖(例如table_name)
所以我的问题是:Rails和
– 如何命名我的课程?
– 他们的目录是什么?
问候
解决方法
但是,我必须首先说,我很惊讶,从组织的角度来看,这个问题是如此强烈.首先我的想法是我是否真的想实现单表继承,然后让它驱动组织问题.通常这里的答案是单表继承不是你实际想要的.但是,让我们来吧!
使用单表继承
以下是使用单表继承使用和组织模型的标准方法:
# app/models/mother_class.rb class MotherClass < ActiveRecord::Base # An "abstract" method def method1 raise NotImplementedError,"Subclasses must define `method1`." end def method2 puts method1 # raises NotImplementedError if `method1` is not redefined by a subclass end end # app/models/sub_class_a.rb class SubClassA < MotherClass def method1 # do something end end # app/models/sub_class_b.rb class SubClassB < MotherClass def method1 # do something end end
鉴于上述,当调用MotherClass.new.method2时,我们将收到异常,但是在调用SubClassA.new.method2或SubClassB.new.method2时不会出现异常.所以我们已经满足了“抽象”的要求.在组织上,你把这个模型文件夹中的这个大块搞砸了,如果你有这些子类或某些东西,我可以理解.但是,请记住,在单表继承中,即使父类也是一个模型,应该是可以使用的!所以说,如果你真的想更好地组织你的模型文件系统,那么你可以自由地这样做.例如,你可以做:
> app / models /< some_organizational_name> /mother_class.rb
> app / models /< some_organizational_name> /sub_class_a.rb
> app / models /< some_organizational_name> /sub_class_b.rb
在这方面,我们正在保留所有其他的东西(即每个模型的代码)是一样的.我们没有以任何方式命名这些模型,我们只是组织它们.为了使这个工作,这只是一个问题,帮助Rails找到我们已经把它们放在模型文件夹的子文件夹中,而没有任何其他线索(即没有命名空间).请参考this other Stack Overflow post.但简而言之,您只需将以下内容添加到您的config / application.rb文件中:
config.autoload_paths += Dir[Rails.root.join('app','models','{**/}')]
使用Mixins
如果您决定单表继承不是您想要的(而且它们通常不是真的),那么混合可以为您提供相同的准抽象功能.而且,您还可以在文件组织方面灵活.混合体的共同组织模式是:
# app/models/concerns/mother_module.rb module MotherModule extend ActiveSupport::Concern # An "abstract" method def method1 raise NotImplementedError,"Subclasses must define `method1`." end def method2 puts method1 # raises NotImplementedError if `method1` is not redefined end end # app/models/sub_class_a.rb class SubClassA include MotherModule def method1 # do something end end # app/models/sub_class_b.rb class SubClassB include MotherModule def method1 # do something end end
使用这种方法,我们继续在调用SubClassA.new.method2或SubClassB.new.method2时得不到异常,因为我们已经在“子类”中覆盖了这些方法.而且由于我们真的不能直接调用MotherModule#method1它当然是一种抽象的方法.
在上述组织中,我们已经将MotherModule放在了模型/关注文件夹中.这是Rails这些天的mixins的常见位置.你没有提到你的rails版本,所以如果你还没有一个模型/关注文件夹,你会想要一个,然后从那里做轨道自动加载模型.这将再次在config / application.rb中使用以下行:
config.autoload_paths += Dir[Rails.root.join('app','concerns','{**/}')]
在我看来,具有混合方式的组织在简单明了,SubclassA和SubClassB是(显然)的模型,由于它们包含了MotherModule的关注点,所以他们得到了MotherModule的行为.如果您想将子类模型(从组织上)分组到一个文件夹中,那么您仍然可以这样做.只需使用上面“单表继承”部分末尾所述的相同方法.但是我可能会将MotherModule保留在模型/关注文件夹中.