Почему Relation.size иногда возвращает хэш в Rails 4

Я могу выполнить запрос двумя разными способами, чтобы вернуть отношение.

Когда я запрашиваю размер отношения, один запрос дает Fixnum, как и ожидалось, другой дает хеш, который является хэшем каждого значения в выражении Relations Group By с количеством вхождений каждого.

Я предполагаю, что в Rails 3 он всегда возвращал Fixnum, поскольку у меня никогда не было проблем, в то время как в Rails 4 он иногда возвращает Hash и выражение вроде Rel.size.zero? дает ошибку:

неопределенный метод `ноль?' для {}: Хэш

Мне лучше просто использовать .blank? метод проверки нулевых записей, чтобы избежать непредвиденных ошибок?

Вот фрагмент кода с операторами логирования для двух запросов и полученный лог.

КОД:

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("-----------------------------------------------------------")

ЖУРНАЛ

-----------------------------------------------------------
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
-----------------------------------------------------------

person giorgio    schedule 15.01.2015    source источник


Ответы (1)


size для объекта ActiveRecord::Relation преобразуется в count, потому что первый пытается получить количество Relation. Но когда вы вызываете count для сгруппированного объекта Relation, вы получаете хэш.

Ключи этого хэша — значения сгруппированного столбца; значения этого хеша являются соответствующими счетчиками.

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

Это верно для следующих методов: count, sum, average, maximum и minimum.

Если вы хотите проверить наличие строк или их отсутствие, просто используйте exists?, т.е. сделайте следующее:

AssessmentResponse.group(:client_id).exists?

Вместо этого:

AssessmentResponse.group(:client_id).count.zero?
person SHS    schedule 15.01.2015
comment
Вы, несомненно, правы, Гумза. Что кажется озадачивающим, так это то, что это должно было измениться для Rail 4, поскольку мой код работал, проверяя «size.zero?» в течение многих лет на Rails 1, 2 и 3. - person giorgio; 16.01.2015