Rails:这是单表继承(STI)的用例吗?

时间:2015-12-01 15:26:43

标签: sql ruby-on-rails database-design database-normalization sti

考虑这个设置。请理解我们的设置更加详细,但这只是一个简单的例子。

competitionname。这是一年一度的比赛。
competition_instances locationstarts_at 每场比赛的sports都有name

例:
competitionname:“超级碗”每年都有不同的competition_instances,但sport保持不变。
相反,competitionname:“奥运会”在每个competition_instances中有不同的sports和不同的competition_instance

最好使用competition_sports创建competition_instance_sportscompetition_instance_sports作为competition_sports的子类吗?

目标:如果存在,请使用competition_instance_sports条记录,否则请使用competition_sports记录。在我们的真实世界应用中,每个比赛/比赛实例可以有20-50个运动记录。我们怎样才能最好地实现?

4 个答案:

答案 0 :(得分:2)

根据我对这个问题的理解,我无法看到STI在这种情况下会有什么帮助。但是,联接表将为您提供所需的位置。

我建议创建一个新表sports,此模型将包含每项运动的所有具体细节。 competition_instance.rb将有一个/多个sport.rbcompetiton.rb会有很多sportscompetition_instance.rb

<强> 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_timeevent_end_time)设置特定属性。

答案 1 :(得分:1)

我只是想到这样的情况,即总会有奥运会的标准运动和一些加入的运动,例如东道国提出的运动。

我会在Polymorphic Associations中使用"reverse manner"

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

答案 2 :(得分:1)

针对“这是STI的用例”的原始问题,如果没有看到环境的完全复杂性,很难说这是否存在。但是这里有一些事情需要考虑:

摘自How (and When) to Use Single Table Inheritance in Rails - eugenius blog

  

在处理共享大部分相同的功能和数据字段 的模型类时,STI应该被视为,但您需要更精细的控制过度扩展或逐个添加到每个类。 STI允许您在编写专用功能时将数据保存在单个表中,而不是复制代码或放弃单个功能。

您已经简化了示例,但听起来像bcompetition基本上不是同一个对象,行为差异很小。根据您所描述的内容,我可能会将这些对象重命名为competition_instanceevent,或者在说明这些对象实际表示的内容方面对您更有意义。我认为“奥运会”是一项普通活动,而“100米短跑”则是在奥运会上举行的比赛。或者“SuperBowl”仅在2014年举办了一场比赛,“SuperBowl XLIX”。

您还使用competition标记了此问题,STI无法提供帮助。如果您的共享对象之间的属性略有不同,那么到处都会出现空字段。

我在这里向您推荐其他答案,看看您应该如何设置这些对象以达到所需的效果。

答案 3 :(得分:0)

这不是单表继承的情况,因为competition_instance不能替代competition而1 competition可以有很多competition_instances。所以你有3个表:

competitions
sports
competition_instances

competition_instancescompetitions的外键,因为1 competition可以有多个competition_instances,但每个competition_instance只有一个competition。< / p>

是否将sports附加到competitionscompetition_instances取决于您的用例的具体限制。我并不确切地知道你的意思是“每个competition/competition_instance可以有20-50个sport记录”。我希望每个competition_instance只有一个sport,因此您可以将其留在那里,或者您也可以将sports的集合附加到competition,所以您可以在competitions之前按sport检索新的competition_instance。我需要有关您的用例的更多详细信息,以便为您提供进一步的建议。