Lighthouse has a new layout. Prefer the old one? Return to the old layout, and switch back any time from the link at the top of each page.

This project is archived and is in readonly mode.

ActiveRecord::Relation#empty? fails for grouped relations, as OrderedHash is missing #zero?

#5829

An activerecord relation with a GROUP BY statement returns an OrderedHash when its calculate method is called, as documented at http://ar.rubyonrails.org/classes/ActiveRecord/Calculations/ClassMe...

When the query returns no results, calling count on it returns an empty OrderedHash. However ActiveRecord::Relation#empty? calls count.zero?, expecting a Number. It in fact gets the OrderedHash producing

NoMethodError: undefined methodzero?' for #<OrderedHash {}>

Simplest thing would be to change the empty? method to be a bit more smart and check for an empty hash before calling zero?. A wider solution would be to implement zero? for OrderedHash.

My workaround right now is to call count.empty? on the relation object but this is ugly. It also only works if you know that the relation object is definitely representing a query that uses GROUP BY, if you dont know that for sure then you have to put ugly conditional statements in because if count returns an integer, #empty? will obviously not be present. Goodbye model-agnostic partials.

Reported by JonnieCache · October 17th, 2010 @ 04:32 PM

State: resolved
Milestone: 3.0.6
Assigned to: nobody
Importance: Low

Activity

  1. Dalibor Filus
    Dalibor Filus

    Today i came over this error too...
    Using Rails 3.0.3, Ruby 1.8.7 Enterprise Edition

    # Showing /var/www/truhlari/app/views/articles/_detail.html.haml where line #103 raised:
    # undefined method `zero?' for #<OrderedHash {"570"=>1, "683"=>1, "551"=>1, "553"=>1}>
    
    # causing line in view:
    if article.more_articles.active.published.any?
    
    # model:
    def more_articles
     ids = self.categories.collect(&:id).compact
     return self.class.scoped.joins("join e3_assocs on `item2_id` = `e3_models`.`id`").where("`item1_id` IN (#{ids.compact.join(',')})").group('`e3_models`.`id`')
    end
    

    Calling .empty? instead of .any? does the same...

    It seems to be solved for my case by using .select("DISTINCT()...")

    But it would not be so easy-solvable for different code cases .. :/

    January 8th, 2011 @ 01:44 PM

  2. mixr
    mixr

    This is quite annoying. But since most results are iterated over anyway, you could just use .to_a.empty? or .all.empty?:
    (of course this is only sensible when limit() is involved)

    @articles = Article.published.group("publisher_id").limit(10).to_a.empty?
    

    Not to speak of other problems with using count() on your ActiveRecord::Relation when limit() or offset() is involved.
    You just cannot use a count/size on a scope and rely on the result.
    for example see: #4882 ActiveRelation bug; size() returning incorrect value with limit().

    February 7th, 2011 @ 04:37 PM

  3. gamov
    gamov

    Same issue for me with the following scope:

      scope :quantity_for_bs, lambda {|bs_id|{
          :joins => :shipment,
          :select =>  '*, SUM (quantity) as total_quantity',
          :group => :item_variant_id,
          :conditions => {:shipments => {:dest_site_id => bs_id}}
      }}
    

    Then if I do

      shi  = ShippingItem.transiting.quantity_for_bs(@business_site.id)
      shi.empty? # <- raises undefined method `zero?' for {}:ActiveSupport::OrderedHash
    

    Interestingly, if I do shi.inspect in between the statements, then .empty? resolves correctly...

    March 6th, 2011 @ 06:54 AM

  4. Dan Pickett
    Dan Pickett
    • State changed from new to open
    • Milestone set to 3.0.6
    • Importance changed from to Low

    Chris Oliver has created a pull request that can help to resolve this issue: https://github.com/rails/rails/pull/218

    March 12th, 2011 @ 05:01 PM

  5. Repository
  6. Chris Oliver