简体   繁体   中英

Rails filter records has_many through

I am trying to search an Item model with a filter named genres that are connected by has_many through.

My problem is when I select two genres or more, it also selects records that contain only one genre.

Example: There are two genres named Action and Adventure. Record A has the Action genre and Record B has both genres. By selecting both the genre checkboxs in my view, the records returned by Rails include both Record A & B while it should have only been Record B.

This is my filter statement under the controller

  //This is under controller
  @item = Item.includes(:genres).where('genres.id' => params['genre_ids'])
  // This is under my view
  <%= simple_form_for Item.new, :method => :get, url: search_path do |f| %>

        <% Genre.all.each do |sc| %>
            <div>
                <label>
              <%= check_box_tag 'genre_ids[]',sc.id %>
                <span style="font-weight:normal;"><%= sc.name %> </span>
             </label>
            </div>
          <% end %>

    <% end %>

The reason it doesn't work is in the SQL that is being created from your expression. where('genres.id' => [1, 2, 3]) gives you SELECT ... WHERE genres.id IN (1,2,3) which is essentially OR-expression.

To fix this, you need to filter the number of selected genres in Ruby or SQL. I would do it with SQL like this:

genre_ids = params['genre_ids']
items = Item.joins(:genres).where('genres.id' => genre_ids).group('items.id').having("count(*) = #{genre_ids.size}")

With this, you will select items with the exact given set of genres. Remember to handle the case with empty genre_ids in the parameters.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM