Antonio
Antonio

Reputation: 751

Rails Activerecord query with an array of objects returns multiple duplicates of objects

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.

enter image description here

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

Answers (1)

Antonio
Antonio

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

Related Questions