ruby-on-rails – Rails – 抽象类定义和文件命名的最佳选择

前端之家收集整理的这篇文章主要介绍了ruby-on-rails – Rails – 抽象类定义和文件命名的最佳选择前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我想定义3个类:

>一个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和
– 如何命名我的课程?
– 他们的目录是什么?

问候

解决方法

首先,我认为你必须已经意识到,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

鉴于上述,当调用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保留在模型/关注文件夹中.

猜你在找的Ruby相关文章