Ruby on rails 使用Ruby On Rails在同一个表之间建立两个关联 我有一个应用程序,有两个模型体育场 >强>团队> /强>,它们有多对多的关系,并通过连接表在中间加入。

Ruby on rails 使用Ruby On Rails在同一个表之间建立两个关联 我有一个应用程序,有两个模型体育场 >强>团队> /强>,它们有多对多的关系,并通过连接表在中间加入。,ruby-on-rails,many-to-many,Ruby On Rails,Many To Many,我当前的结构如下所示: class Team < ActiveRecord::Base has_many :stadiumteams, :class_name => 'StadiumTeam' has_many :stadiums, :through => :stadiumteams end class Stadium < ActiveRecord::Base has_many :stadiumteams, :class_name => '

我当前的结构如下所示:

class Team < ActiveRecord::Base
    has_many :stadiumteams, :class_name => 'StadiumTeam'
    has_many :stadiums, :through => :stadiumteams
end

class Stadium < ActiveRecord::Base
    has_many :stadiumteams, :class_name => 'StadiumTeam'
    has_many :teams, :through => :stadiumteams
end

class StadiumTeam < ActiveRecord::Base
    belongs_to :stadium
    belongs_to :team
end

有几种方法可以满足您的需求。您的方法也足够了,但为了提高效率,因为体育场的数量很小(数千),所以您可以将STI用于
体育场
实体

class Stadium < ActiveRecord::
  has_many :stadiums_teams
  has_many :teams, through: :stadiums_teams
end

class OldStadium < Stadium; end

class RecentStadium < Stadium; end

class StadiumTeam < ActiveRecord::Base
  belongs_to :stadium
  belongs_to :team
end

class Team < ActiveRecord::Base
  has_many :stadiums_teams
  has_many :stadiums, through: :stadiums_teams, source: :stadium
  has_many :old_stadiums, through: :stadiums_teams,
    source: :stadium, class_name: OldStadium.name
  has_many :recent_stadiums, through: :stadiums_teams,
    source: :stadium, class_name: RecentStadium.name
end
class体育场

因此,在大多数情况下,您将使用
OldStadium
/
RecentStadium
模型,但当您想检查一支球队是否曾在特定体育场比赛时,只需使用
stadium
模型。

您可以定义与lambda的关系,以便在关系中附加一个
where
子句:

class Team < ActiveRecord::Base
    has_many :stadiumteams, :class_name => 'StadiumTeam'

    has_many stadiums, :through => :stadiumteams
    has_many :current_stadiums, ->{ where(stadiumteams: { current_home: true }) }, :through => :stadiumteams, :class_name => 'Stadium', :source => :stadium
    has_many :previous_stadiums, ->{ where(stadiumteams: { current_home: false }) }, :through => :stadiumteams, :class_name =>'Stadium', :source => :stadium
end

class Stadium < ActiveRecord::Base
    has_many :stadiumteams, :class_name => 'StadiumTeam'

    has_many :teams, :through => :stadiumteams
    has_many :current_teams, ->{ where(stadiumteams: { current_home: true }) }, :through => :stadiumteams, :class_name => 'Team', :source => :team
    has_many :previous_teams, ->{ where(stadiumteams: { current_home: false }) }, :through => :stadiumteams, :class_name =>'Team'. :source => :team
end

class StadiumTeam < ActiveRecord::Base
    belongs_to :stadium
    belongs_to :team
end

您可以在联接表中添加开始和结束日期列,因此当
StadiumTeam
记录有开始日期但没有结束日期时,它表示“该队是该体育场的当前居民”,如果有结束日期,您可以猜出其含义。要在Rails(当前和以前的“常驻”团队)中定义这两个关系,您可以在关系中添加lambda:
有许多:当前体育场,->{where(体育场队:{end_date:nil}},通过::stadiumteams
,对于
以前的体育场
来说大致相同,但是
结束日期不为null
。确定。谢谢你的快速回复。实际上,我已经有了一个名为current_home fin my statiumteam Table的布尔列。因此,也许我可以有两个输入字段,其中一个将布尔值设置为true(如果当前home),另一个字段将值设置为false(如果不是当前home)?但我不确定我将如何做到这一点。在原始帖子中添加了我输入的代码。我建议您使用DateTime字段,因为它们的存在可以充当布尔值,但会带来更多信息。布尔值为您提供所能获得的最小数据量,而DateTime字段则告诉您相同的答案,但数据量更多。在你的上下文中,如果你想建立XX队居住过的所有体育场的历史,你不能用布尔列,但可以用DateTime列轻松地完成。你有几个选项,我建议的一个是基于该布尔定义2个关系,所以,
体育场
有很多:老队,{where(体育场队:{current_home:false}}),通过::体育场队,班级名称:'stadiumteams'
。然后你可以在你的HTML表单中执行
f.association:old_stadiums[…]
,它应该将这个
current_home
自动设置为
false
是的,这是一个很好的观点。只是想增加新的体育场馆是一个非常简单的过程,我也希望能够增加大量的球队,以防一个体育场有很多球队。在很多情况下,我不会有“结束日期”的信息,因此信息不会非常准确。尽管如此。我对编程很陌生,如果你的建议是使用DATETIME,我会考虑的。谢谢。但是当我执行第三个命令时,控制台中会出现错误。>>>“ActiveRecord::HasmanyThroughSourceAssociationNotFound错误:在模型体育场团队中找不到源关联“previous_stadium”或:previous_stadium。请尝试“has_many:previous_stadium,:through=>:StadiumTeam,:source=>”。它是体育场还是团队之一?”@tommers我更新了我的答案,将
源代码
选项包含在
有很多
中,再次感谢。但现在我得到了:(仍然在第3个命令中)ActiveRecord::UnknownAttributeError:体育场的未知属性'stadium\u id'。当我使用f.association:current\u stadiums做这件事时,在部分表格中我得到:“association:current\u stadiums not found”我更新了我的答案,并修复了rails控制台代码和
f.association
部分
class OldStadium < ActiveRecord::Base
    belongs_to :stadium
    belongs_to :team
end
<%= f.association :teams, label: 'Current Residents', class:'select2-field', placeholder: "Select teams", collection: @teams, input_html: { multiple: true }, hint: 'Select one or multiple teams.'%>

<%= f.association :teams, label: 'Old Residents', class:'select2-field', placeholder: "Select teams", collection: @teams, input_html: { multiple: true }, hint: 'Select one or multiple teams.' %>
   def stadium_params
      params.require(:stadium).permit(:name, :capacity, :city, :country, :location_name, :address, :longitude, :latitude, :image, :surface, :official_opening_date, :cost, :web_url, :also_known_as, :record_attendance, :team_ids => [])
    end
class Stadium < ActiveRecord::
  has_many :stadiums_teams
  has_many :teams, through: :stadiums_teams
end

class OldStadium < Stadium; end

class RecentStadium < Stadium; end

class StadiumTeam < ActiveRecord::Base
  belongs_to :stadium
  belongs_to :team
end

class Team < ActiveRecord::Base
  has_many :stadiums_teams
  has_many :stadiums, through: :stadiums_teams, source: :stadium
  has_many :old_stadiums, through: :stadiums_teams,
    source: :stadium, class_name: OldStadium.name
  has_many :recent_stadiums, through: :stadiums_teams,
    source: :stadium, class_name: RecentStadium.name
end
class Team < ActiveRecord::Base
    has_many :stadiumteams, :class_name => 'StadiumTeam'

    has_many stadiums, :through => :stadiumteams
    has_many :current_stadiums, ->{ where(stadiumteams: { current_home: true }) }, :through => :stadiumteams, :class_name => 'Stadium', :source => :stadium
    has_many :previous_stadiums, ->{ where(stadiumteams: { current_home: false }) }, :through => :stadiumteams, :class_name =>'Stadium', :source => :stadium
end

class Stadium < ActiveRecord::Base
    has_many :stadiumteams, :class_name => 'StadiumTeam'

    has_many :teams, :through => :stadiumteams
    has_many :current_teams, ->{ where(stadiumteams: { current_home: true }) }, :through => :stadiumteams, :class_name => 'Team', :source => :team
    has_many :previous_teams, ->{ where(stadiumteams: { current_home: false }) }, :through => :stadiumteams, :class_name =>'Team'. :source => :team
end

class StadiumTeam < ActiveRecord::Base
    belongs_to :stadium
    belongs_to :team
end
team = Team.first
stadium = Stadium.first
team.previous_stadiums <<
team.save
team.reload.previous_stadiums.include?(stadium) 
# => should return true
f.association :current_teams, #...