对于我的一个联接表,我想根据下拉菜单选择过滤结果。在我进一步解释之前,我将提供相关代码。
我有3个模型:
class Scoreboard
has_many :teams, has_many :team_matches
end
class Team
belongs_to Scoreboard
#self reference with the teams to create team_matches.
has_many :first_team, class_name: "TeamMatch", foreign_key: "team_a_id", dependent: :destroy
has_many :team_a, through: :first_team, source: :team_a
has_many :second_team, class_name: "TeamMatch", foreign_key: "team_b_id", dependent: :destroy
has_many :team_b, through: :second_teams, source: :team_b
end
最终的模型是团队的联接表:
class Team_Match
belongs_to :team_a, class_name: "Team"
belongs_to :team_b, class_name: "Team"
belongs_to :scoreboard
end
团队匹配索引视图的控制器代码:
class TeamMatchesController < ApplicationController
require 'will_paginate/array'
def index
@selected = true
@scoreboard = Scoreboard.find(params[:scoreboard_id])
@teams = @scoreboard.teams
@matches = @scoreboard.team_matches.order("match_date DESC").paginate(page: params[:page], per_page: 5)
end
end
索引页面视图:
<h2 class="team-matches-header">TEAM MATCHES</h2>
<% if manager_or_owner?(@scoreboard, current_user) %>
<%= link_to "Add Matches", new_scoreboard_team_match_path(@scoreboard), class: "btn btn-primary" %>
<%= link_to "Clear Matches", deletematches_scoreboard_path(@scoreboard),method: :delete, class: "btn btn-danger", :data => {:confirm => "Are you absolutely sure you want to delete all matches?"} %>
<% end %>
<%= form_tag(scoreboard_team_matches_path, :method => "get", id: "match-search-form", autocomplete: "off") do %>
<div class="row new-member-field">
<div class="col-xs-12 col-sm-6">
<%= select_tag "teams", options_from_collection_for_select(@teams, "id", "name"), prompt: "Select something", class:"form-control" %>
<%= submit_tag 'Filter' %>
</div>
</div>
<% end %>
<div class="match-list">
<%= render 'match_list' %>
</div>
匹配列表部分
<% if @matches.present? %>
<% @matches.each do |game| %>
<div class="row match-div clearfix" id="match_<%= game.id %>">
<div class="col-xs-12 match-column">
<div class="facing-teams">
<div class="first-team">
<%= game.team_a.name %>
</div>
<div class="second-team">
<%= game.team_b.name %>
</div>
</div>
</div>
</div>
<% end %>
<% end %>
<div class="row">
<div class="col-xs-12 new-member-pages">
<%= will_paginate @matches %>
</div>
</div>
到目前为止,在团队匹配索引页面上,我已经能够将下拉菜单选项与团队列表放在一起。我遇到的麻烦就是如何让它发挥作用。从下拉列表中选择提交团队后,我想显示一个匹配对象列表(@matches),其:team_a_id
或:team_b_id
与所选团队的ID匹配。我该怎么做呢?
答案 0 :(得分:1)
我会用scopes来达到你想要的效果。范围是可重复使用的过滤器,您可以将其应用于关联以准确查找所需的记录。
这是您创建查找特定团队匹配的范围的方法:
class Team_Match
scope :has_team, ->(team_id) {
team_a = arel_table[:team_a_id].eq(team_id)
team_b = arel_table[:team_b_id].eq(team_id)
team_a_or_b = team_a.or(team_b)
where(team_a_or_b)
}
end
这使用arel(ActiveRecord使用它来创建SQL查询),以便在team_a_id
或team_b_id
列中找到匹配项。如果您不知道上述代码的用途,请快速前往Mastering AR and Arel以加快速度。
你使用这样的范围:
matches = Team_Match.has_team(team_id)
您还可以在加入Team_Match
的任何关系中使用范围:
matches = @scoreboard.team_matches.has_team(team_id)
范围也可以链接在一起:
matches = @scoreboard.team_matches.has_team(team_id).where(match_date: today)
范围允许您从选择框传入团队ID以查找匹配项:
def index
@selected = true
@scoreboard = Scoreboard.find(params[:scoreboard_id])
@teams = @scoreboard.teams
@matches = @scoreboard.team_matches.order("match_date DESC")
@matches = @matches.paginate(page: params[:page], per_page: 5)
# we apply the scope (if present) to only show the matches for the selected team
if (team_id = params[:selected_team_id])
@matches = @matches.has_team(team_id)
end
end
您需要对上述代码进行的唯一更改是确定保存所选团队ID的param变量的实际名称。