通过下拉菜单在连接表中缩小元素。 (导轨4)

时间:2016-05-30 23:53:58

标签: ruby-on-rails postgresql

对于我的一个联接表,我想根据下拉菜单选择过滤结果。在我进一步解释之前,我将提供相关代码。

我有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匹配。我该怎么做呢?

1 个答案:

答案 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_idteam_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变量的实际名称。