【问题标题】:Rails Activerecord query with an array of objects returns multiple duplicates of objects带有对象数组的 Rails Activerecord 查询返回多个对象副本
【发布时间】:2017-03-01 06:38:11
【问题描述】:

我有一系列复选框,用户可以使用这些复选框通过选中的属性来查找对象。我希望他们能够选择许多属性,然后显示包含所有已检查属性的对象列表。

我的代码部分工作,除了如果我检查一个属性并给我一个列表,然后我检查另一个属性,该属性已经从上一次检查中显示,那么我会得到另一个副本。这是正在发生的事情的图像。请注意,对象正在重复。

这是附带的代码:

<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;
});

活动记录查询所在的控制器。

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

我确定这是 Activerecord 问题而不是显示问题,因为如果我检查 @objects,我会看到多个记录副本,如下所示:

[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

【问题讨论】:

  • 请注意确定这是否能解决问题,但问题可能与您的模型被称为 Object 的事实有关。我强烈建议您将其重命名为更能描述其所拥有数据的名称。 Object 是 ruby​​ 中最基本的类之一的名称,如果您将其用作模型,您可能会遇到一些微妙的命名空间冲突,并且可能会看到极其奇怪的行为。我不认为这与您当前的问题有关,但可能与您当前的问题有关,但您应该更改它。
  • 这样做是为了掩盖我正在处理的数据。不是真的叫Object
  • 好吧,那没关系。我实际上想知道你是如何设法让 Object 首先继承 ActiveRecord::Base 的!

标签: ruby-on-rails ruby activerecord


【解决方案1】:

在我的查询末尾添加.distinct 解决了我的问题,并将省略重复记录。

我现在的工作查询是:

@objects = Object.joins(:packages).where("packages.kind IN (?)", packages).distinct

【讨论】:

  • 我认为这是 SQL 连接的一个怪癖,它允许在某些情况下返回重复项。您使用 distinct 的解决方案在这里似乎是正确的。
猜你喜欢
  • 2021-12-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多