我正在开发一个非常大的Rails应用程序。我们最初没有使用太多继承,但我们从一位顾问那里获得了一些令人大开眼界的经验,并正在寻求重构我们的一些模型。
我们的应用程序中有很多以下模式:
class Project < ActiveRecord::Base
has_many :graph_settings
end
class GraphType < ActiveRecord::Base
has_many :graph_settings
#graph type specific settings (units, labels, etc) stored in DB and very infrequently updated.
end
class GraphSetting < ActiveRecord::Base
belongs_to :graph_type
belongs_to :project
# Project implementation of graph type specific settings (y_min, y_max) also stored in db.
end
这也会在视图、助手和GraphSetting模型本身中产生大量的条件。所有这些都不是好事。
一个简单的重构,我们去掉了GraphType,转而使用更像这样的结构:
class Graph < ActiveRecord::Base
belongs_to :project
# Generic methods and settings
end
class SpecificGraph < Graph
# Default methods and settings hard coded
# Project implementation specific details stored in db.
end
现在,这对我来说非常有意义,简化了测试,删除了条件条件,并使以后的国际化更容易。然而,我们只有15到30个图表。
我们有一个非常相似的模型(作为例子使用起来很复杂),大约有100种不同的“类型”,而且可能会翻一番。它们都有继承的关系和方法,其中一些需要覆盖比其他方法更多的方法。这看起来是完美的用法,但这么多的用法似乎很多。
200个STI类对很多人来说是不是很多?有没有其他我们应该看的模式?
谢谢你的智慧,我会回答任何问题。
发布于 2010-09-10 00:07:15
如果区别仅仅是类的行为,那么我认为这不应该是一个问题,这是STI的一个很好的候选者。(请注意,我从来没有用这么多的子类尝试过这种方法。)
但是,如果您的200个STI类都有一些独特的属性,那么在主表中将需要大量额外的数据库列,这些列在99.5%的情况下将是NULL。这可能是非常低效的。
为了创建类似于“多表继承”的东西,我之前成功地使用了一些元编程来关联其他表,以获得每个类唯一的细节:
class SpecificGraph < Graph
include SpecificGraphDetail::MTI
end
class SpecificGraphDetail < ActiveRecord::Base
module MTI
def self.included(base)
base.class_eval do
has_one :specific_graph_detail, :foreign_key => 'graph_id', :dependent => :destroy
delegate :extra_column, :extra_column=, :to => :specific_graph_detail
end
end
end
end
委托意味着您可以访问关联的详细信息字段,就像它们直接在模型上一样,而不是通过specific_graph_detail
关联,而且对于所有意图和目的,它“看起来”就像是额外的列。
您必须权衡需要连接这些额外细节表的情况和仅在主表中拥有额外列的情况。这将决定是使用STI还是使用关联表的解决方案,如我上面的解决方案。
https://stackoverflow.com/questions/3677924
复制相似问题