Why Relation.size Sometimes Returns Hash in Rails 4

I can run the query in two different ways to return a Relation.

When I request the size of the relationship, one request gives Fixnum, as expected, the other gives a hash, which is the hash of each value in the Group Group By expression with the number of occurrences of each.

In Rails 3, I assume it always returned Fixnum, since I never had a problem with Rails 4, sometimes it returns a hash and an operator like Rel.size.zero? gives an error:

undefined method `zero? 'for {}: Hash

Am I using .blank best? null record verification method to avoid unforeseen errors?

Here is a code snippet with looging statements for two queries and the resulting log

CODE:

assessment_responses1=AssessmentResponse.select("process").where("client_id=? and final = ?",self.id,false).group("process") logger.info("-----------------------------------------------------------") logger.info("assessment_responses1.class = #{assessment_responses1.class}") logger.info("assessment_responses1.size.class = #{assessment_responses1.size.class}") logger.info("assessment_responses1.size value = #{assessment_responses1.size}") logger.info("............................................................") assessment_responses2=AssessmentResponse.select("distinct process").where("client_id=? and final = ?",self.id,false) logger.info("assessment_responses2.class = #{assessment_responses2.class}") logger.info("assessment_responses2.size.class = #{assessment_responses2.size.class}") logger.info("assessment_responses2.size values = #{assessment_responses2.size}") logger.info("-----------------------------------------------------------") 

LOG

 ----------------------------------------------------------- assessment_responses1.class = ActiveRecord::Relation::ActiveRecord_Relation_AssessmentResponse (0.5ms) SELECT COUNT(`assessment_responses`.`process`) AS count_process, process AS process FROM `assessment_responses` WHERE `assessment_responses`.`organisation_id` = 17 AND (client_id=43932 and final = 0) GROUP BY process assessment_responses1.size.class = Hash CACHE (0.0ms) SELECT COUNT(`assessment_responses`.`process`) AS count_process, process AS process FROM `assessment_responses` WHERE `assessment_responses`.`organisation_id` = 17 AND (client_id=43932 and final = 0) GROUP BY process assessment_responses1.size value = {"6 Month Review(1)"=>3, "Assessment(1)"=>28, "Assessment(2)"=>28} ............................................................ assessment_responses2.class = ActiveRecord::Relation::ActiveRecord_Relation_AssessmentResponse (0.5ms) SELECT COUNT(distinct process) FROM `assessment_responses` WHERE `assessment_responses`.`organisation_id` = 17 AND (client_id=43932 and final = 0) assessment_responses2.size.class = Fixnum CACHE (0.0ms) SELECT COUNT(distinct process) FROM `assessment_responses` WHERE `assessment_responses`.`organisation_id` = 17 AND (client_id=43932 and final = 0) assessment_responses2.size values = 3 ----------------------------------------------------------- 
+7
activerecord ruby-on-rails-4 arel
source share
1 answer

size of the ActiveRecord::Relation object translates to count , because the first one tries to get the Relation counter. But when you call count on a grouped Relation object, you get a hash.

The keys to this hash are grouped column values; the values ​​of this hash are the corresponding values.

 AssessmentResponse.group(:client_id).count # this will return a Hash AssessmentResponse.group(:client_id).size # this will also return a Hash 

This is true for the following methods : count , sum , average , maximum and minimum .

If you want to check for rows or not, just use exists? ie follow these steps:

 AssessmentResponse.group(:client_id).exists? 

Instead of this:

 AssessmentResponse.group(:client_id).count.zero? 
+10
source share

All Articles