[英]rails, SQL, Single Table Inheritance, table addressed as “subclass” not as class
[英]Rails: Is this a use case for Single Table Inheritance (STI)?
考虑这个设置。 请理解我们的设置更加详细,但这只是一个简单的例子。
competition
其中有name
。 这是一年一度的比赛。
competition_instances
其中有location
, starts_at
。
每个比赛都有name
sports
。
例:
competition
。 name
:“超级碗”每年都有不同的competition_instances
实例,但sport
保持不变。
相反, competition
。 name
:“奥运会”在每场competition_instance
都有不同的competition_instances
和不同的sports
。
会是最好创建competition_sports
和competition_instance_sports
与competition_instance_sports
作为一个子类competition_sports
?
目标 :使用competition_instance_sports
记录(如果存在),否则使用competition_sports
记录。 在我们的真实世界应用中,每个比赛/比赛实例可以有20-50个运动记录。 我们怎样才能最好地实现?
根据我对这个问题的理解,我无法看到STI在这种情况下会有什么帮助。 但是,连接表将为您提供所需的位置。
我建议创建一个新的表sports
,这个模型将具有每项运动的所有具体细节。 competition_instance.rb
将有一个/多个sport.rb
。 competiton.rb
将通过competition_instance.rb
进行多项sports
。
competition.rb
Class Competition < ActiveRecord::Base
has_many :competition_instances
has_many :sports, through: :competition_instances
end
competition_instance.rb
Class CompetitionInstance < ActiveRecord::Base
belongs_to :competition
belongs_to :sport
end
sport.rb
Class Sport < ActiveRecord::Base
has_many :competition_instances
end
通过使用此设计,您将能够实现以下目标:
1-您将在数据库中拥有预定义的运动及其特定属性。
2-每场比赛都将有.sports
,这将为本次奥运会比赛提供所有体育项目。
3-您将能够在竞争实例表中为每个竞赛实例(例如event_start_time
和event_end_time
)设置特定属性。
我只想到这样的情况,那里有标准的体育运动,这些体育运动总是在奥运会上,还有一些是加入的,例如东道国提出的那些。
class Competition < ActiveRecord::Base
has_many :competition_instances
has_many :competition_sports, as: :event
end
class CompetitionInstance < ActiveRecord::Base
belongs_to :competition
has_many :competition_sports, as: :event
def events_array # neater by sacrificing ActiveRecord methods
competition.competition_sports + competition_sports
end
def events # messier, returns ActiveRecord relationship
CompetitionSport.where( " ( event_id = ? AND event_type = 'Competition' ) OR
( event_id = ? AND event_type = 'CompetitionInstance')", competition_id, id )
end
end
class Sport < ActiveRecord::Base
has_many :events, as: :competition_sport
end
class CompetitionSport < ActiveRecord::Base
belongs_to :sport
belongs_to :event, polymorphic: true
end
这允许:
competition.competition_sports # standard sports
competition_instance.competition_sports # only those specific for this instance
competition_instance.events # includes sports from both
针对“这是STI的用例”的原始问题,如果没有看到环境的完全复杂性,很难说这是否存在。 但是这里有一些事情需要考虑:
摘自在Rails中使用单表继承的方式(和何时) - eugenius blog :
在处理共享大部分相同功能和数据字段的模型类时,应考虑 STI,但您希望对单独扩展或添加每个类进行更精细的控制。 STI允许您在编写专用功能时将数据保存在单个表中,而不是重复代码或放弃单个功能。
你已经简化了你的例子,但听起来像competition
和competition_instance
本质上不是同一个对象,行为差异很小。 根据您所描述的内容,我可能会将这些对象重命名为event
和competition
,或者在说明这些对象实际代表的内容方面对您更有意义。 我认为“奥运会”是一项普通活动,而“100米短跑”则是在奥运会上举行的比赛。 或者“SuperBowl”仅在2014年举办了一场“SuperBowl XLIX”比赛。
您还使用database-normalization
标记了此问题,STI无法提供帮助。 如果您的共享对象之间的属性略有不同,那么到处都会出现空字段。
我在这里向您推荐其他答案,看看您应该如何将这些对象设置为符合要求。
这不是单表继承的情况,因为competition_instance
不能代替competition
,1 competition
可以有很多competition_instances
实例。 所以你有3个表:
competitions
sports
competition_instances
competition_instances
有一个外键competitions
,因为:1间competition
可以有很多competition_instances
但每个competition_instance
都有一个确切的competition
。
无论是将sports
与competitions
还是competition_instances
实体相关,都取决于您的用例的具体限制。 我并不确切地知道你的意思是“每场competition/competition_instance
实例可以有20-50个sport
记录”。 我希望每个competition_instance
到有一个确切的sport
,所以你可能会离开它,否则你可能会附加集合sports
的competition
为好,这样您就可以获取新的competitions
用sport
之前还有一个competition_instance
。 我需要有关您的用例的更多详细信息,以便为您提供进一步的建议。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.