pie*_*ard 13 abstract-class model ruby-on-rails
我想定义3个类:
MotherClass(摘要,无法推断)SubClassA(继承自MotherClass)SubClassB(继承自MotherClass)在Rails中声明它的最佳解决方案是什么?
1.将所有内容放入app/models /
MotherClass < AR::Base 在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 在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 在app/models/mother_module/base.rb中MotherModule::SubClassA < MotherModule::Base 在app/models/mother_module/sub_class_a.rb中MotherModule::SubClassB < MotherModule::Base 在app/models/mother_module/sub_class_b.rb中优点:非常干净
不方便:需要一些函数Base来覆盖(例如table_name)
所以我的问题是:Rails中的最佳实践是什么? - 如何命名我的课程? - 他们的目录是什么?
pdo*_*obb 15
首先,我认为你必须已经意识到ruby没有真正的抽象类.但我们可以近似这种行为.在这样做的同时,听起来你对组织结构有偏好,我将尝试解决这个问题.
但是,我必须先说,我很惊讶你从组织的角度来看这个问题是如此强烈.首先,我的想法是我是否真的想要实现单表继承,然后让它驱动组织问题.通常这里的答案是单表继承不是你真正想要的.但是......让我们潜入!
以下是使用单表继承来利用和组织模型的标准方法:
# 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
Run Code Online (Sandbox Code Playgroud)
鉴于上述情况,我们会打电话时得到一个异常MotherClass.new.method2而不是调用时SubClassA.new.method2或SubClassB.new.method2.所以我们满足了"抽象"的要求.在组织上,你把它称为模型文件夹中的一个大混乱...如果你有大量的这些子类或其他东西,我可以理解.但是,请记住,在单表继承中,即使那么父类也是一个模型,并且/应该可以这样使用!所以,如果您真的想要更好地组织模型文件系统,那么您可以自由地这样做.例如,您可以这样做:
app/models/<some_organizational_name>/mother_class.rbapp/models/<some_organizational_name>/sub_class_a.rbapp/models/<some_organizational_name>/sub_class_b.rb在这方面,我们保持所有其他事物(即每个模型的代码)相同.我们不会以任何方式命名这些模型,我们只是组织它们.为了完成这项工作,现在只需要帮助Rails找到模型,我们已经将它们放在模型文件夹的子文件夹中而没有任何其他线索(即没有命名空间).有关此信息,请参阅此其他Stack Overflow帖子.但是,简而言之,您只需将以下内容添加到config/application.rb文件中:
config.autoload_paths += Dir[Rails.root.join('app', 'models', '{**/}')]
Run Code Online (Sandbox Code Playgroud)
如果您认为单表继承不是您想要的(而且它们通常不是,那么)mixins可以为您提供相同的准抽象功能.而且,您可以再次灵活地进行文件组织.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
Run Code Online (Sandbox Code Playgroud)
使用这种方法,我们在调用时仍然没有得到异常,SubClassA.new.method2或者SubClassB.new.method2因为我们在"子类"中重写了这些方法.因为我们不能MotherModule#method1直接调用它当然是一种抽象方法.
在上面的组织中,我们已经隐藏MotherModule在models/concerns文件夹中.这是目前Rails中mixins的常见位置.你没有提到你所使用的rails版本,所以如果你还没有一个models/concerns文件夹,你可以制作一个,然后从那里制作rails自动加载模型.这将再次在config/application.rb中完成,其中包含以下行:
config.autoload_paths += Dir[Rails.root.join('app', 'concerns', '{**/}')]
Run Code Online (Sandbox Code Playgroud)
在我看来,使用mixins方法的组织简单明了,SubclassA并且SubClassB(显然)是模型,因为它们包括MotherModule关注他们得到的行为MotherModule.如果你想在组织上将子类模型分组到一个文件夹中,那么你当然还可以这样做.只需使用上面单表继承部分末尾概述的相同方法.但我可能仍然MotherModule位于models/concerns文件夹中.
| 归档时间: |
|
| 查看次数: |
13199 次 |
| 最近记录: |