使用HAVING子句从ActiveRecord查询中排除'nil'行,其中不返回任何结果

时间:2015-07-11 02:09:04

标签: ruby-on-rails ruby-on-rails-3 activerecord

我正在模型中构建一系列方法以用作范围。当其中一个使用having子句并且该查询没有返回任何结果时,我得到一个返回模型的实例,其中所有字段都是nil,并且这打破了我想要使用这些范围的大多数代码。

下面是一个高度简化的示例,用于演示我的问题。

class Widget < ActiveRecord::Base
  attr_accessible :name

  has_many :components

  def without_components
    joins(:components).group('widgets.id')having('COUNT(components.id) = 0')
  end

  def without_components_and_remove_nil
    without_components.select{|i| i.id} # Return objects where i.id is not nil
  end
end

如果所有窗口小部件都已分配了组件,则调用Widget.without_components将返回不合需要的内容:

[{id: nil, name: nil, user_id: nil}]

但是如果我调用Widget.without_components_and_remove_nil它会将ActiveRecord::Relation对象转换为Array,因此我无法将其与其他作用域链接起来。< / p>

是否有办法更改范围,以便在出现nil行时将其排除,或者是否可以对我的ActiveRecord查询进行修改以使其有效?

1 个答案:

答案 0 :(得分:0)

我需要解决两个问题才能使该范围有效;一个与我原来的问题没有关系的,虽然上面提到的范围在没有它的情况下不会被修复:

  • 首先,直接处理手头的问题,因为Rails 3.1你可以这样做:

Widget.where(id: Widget.joins(:components).group('widgets.id').having('COUNT(components.id)'))
  • 其次,joins(:components)部分无法与having('COUNT(components.id = 0)')一起使用,因为joins执行内部联接,因此该查询永远不会有任何结果。我必须将joins替换为joins("LEFT OUTER JOIN components ON components.widget_id = widgets.id")