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.