Reputation: 751
I have a series of checkboxes a user can use to find objects by the checked attributes. I want them to be able to select a number of attributes and then be shown a list of objects that contain all of those checked attributes.
My code is partially working, except that if I check one attribute and I'm given a list and then I check another attribute, that was already displayed from the previous check, then I'm given another copy. Here is an image of what is happening. Notice that objects are being repeated.
Here is the code that goes with it:
<div class="col-md-2">
<div class="dropdown package-dropdown">
<button class="btn btn-secondary dropdown-toggle" type="button" id="dropdownMenuButton" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">Attributes</button>
<ul class="dropdown-menu" aria-labelledby="dropdownMenuButton">
<li><a href="#" class="small" data-value="attr1" tabIndex="-1"><input type="checkbox"/>attr1</a></li>
<li><a href="#" class="small" data-value="attr2" tabIndex="-1"><input type="checkbox"/>attr2</a></li>
<li><a href="#" class="small" data-value="attr3" tabIndex="-1"><input type="checkbox"/>attr3</a></li>
<li><a href="#" class="small" data-value="attr4" tabIndex="-1"><input type="checkbox"/>attr4</a></li>
<li><a href="#" class="small" data-value="attr5" tabIndex="-1"><input type="checkbox"/>attr5</a></li>
</ul>
</div>
</div>
<!-- removed irrelevant code for brevity -->
<tbody id="hits">
<% @objects.each do |obj| %>
<tr>
<td><%= link_to obj.title, obj_path(obj) %></td>
<td class="package-column">
<% if obj.packages.any? %>
<div>
<% obj.packages.each do |p| %>
<span><%= image_tag "needs-#{p.kind}", :alt => "#{p.kind}", :class => "foobar" %></span>
<% end %>
</div>
<% else %>
<div class="package-column"><span>...</span></div>
<% end %>
</td>
<td><%= obj.capacity %></td>
<td><%= obj.started_at.strftime('%A, %B %e, %Y at %l:%M %p') if obj.started_at? %></td>
</tr>
<% end %>
<tr><td colspan="4" align="center"><%= link_to "Load More", objects_path, class: "load-more" %></td></tr>
</tbody>
</table>
var options = [];
$('.dropdown-menu li a').on( 'click', function(event) {
var $target = $( event.currentTarget ),
val = $target.attr( 'data-value' ),
$inp = $target.find( 'input' ),
idx;
if ( ( idx = options.indexOf( val ) ) > -1 ) {
options.splice( idx, 1 );
setTimeout( function() { $inp.prop( 'checked', false ) }, 0);
} else {
options.push( val );
setTimeout( function() { $inp.prop( 'checked', true ) }, 0);
}
$( event.target ).blur();
console.log( options );
$.ajax({
url: $(this).attr('href'),
type: "GET",
data: {
packages: options
},
dataType: "script"
})
return false;
});
My controller where the active record query is.
def index
if params[:packages]
packages = params[:packages] # ["attr1", "attr3" etc..]
@objects = Object.joins(:packages).where("packages.kind IN (?)", packages)
end
respond_to do |format|
format.html
format.js
end
end
I am sure it's an Activerecord issue and not a display issue because if I inspect @objects
I'm shown multiple copies of records like so:
[8] pry(#<ObjectsController>)> @objects
=> [#<Object:0x007f991cb1d6b0
id: 2,
uuid: "1adede0e-8585-41a5-8c74-8de8eec6a141",
name: "andy-title1",
title: "Andy - Title1",
started_at: Mon, 27 Mar 2017 13:00:24 PDT -07:00,
ended_at: Mon, 27 Mar 2017 18:00:24 PDT -07:00
#<Object:0x007f991cb1d548
id: 2,
uuid: "1adede0e-8585-41a5-8c74-8de8eec6a141",
name: "andy-title1",
title: "Andy - Title1",
started_at: Mon, 27 Mar 2017 13:00:24 PDT -07:00,
ended_at: Mon, 27 Mar 2017 18:00:24 PDT -07:00
Upvotes: 1
Views: 748
Reputation: 751
Adding .distinct
to the end of my query solved my issues and will omit duplicate records.
My now working query is:
@objects = Object.joins(:packages).where("packages.kind IN (?)", packages).distinct
Upvotes: 2