Подтвердить что ты не робот

Rails: правильный способ превратить отношение activerecord к массиву?

Я пытался выбрать объекты uniq по одному атрибуту, используя @videos.uniq{|p| p.author}

  time = Time.new(2014, 12)
  start_time = time.beginning_of_month
  end_time = time.end_of_month

  videos = Video.where("created_at > ? AND created_at < ?", start_time, end_time).where("likes > ?", 15)
  selected_videos = videos.uniq{|p| p.author}
  puts videos.count, videos.class, selected_videos.count 
 #=> 23, Video::ActiveRecord_Relation, 23

  videos_first = videos.first(23)
  selected_videos = videos_first.uniq{|p| p.author}
  puts videos_first.count, videos_first.class, selected_videos.count
  #=> 23, array, 10

.uniq не для ActiveRecord_Relation. И проблема в том, что запрос возвращает Video::ActiveRecord_Relation, но мне нужно array.

Конечно, это может быть достигнуто с помощью to_a, но является ли это элегантным?

  • Каков правильный способ решения этой проблемы?
  • Можно ли использовать .uniq для activerecord:relation?
4b9b3361

Ответ 1

Если вам нужен доступ к результату запроса, просто используйте #to_a в экземпляре ActiveRecord:: Relation.

В направляющих rails вы можете найти заметные изменения в Rails 4.0: "Model.all теперь возвращает ActiveRecord:: Relation, а не массив записей. Используйте Relation # to_a, если вам действительно нужен массив. В некоторых конкретных случаях это может привести к поломке при обновлении". Это справедливо для других методов отношений, таких как: where.

 selected_videos = videos.to_a.uniq{|p| p.author}

Ответ 2

.uniq не имеет большого смысла, когда он применяется к полной записи активной записи.

Учитывая, что по крайней мере один или несколько из трех атрибутов - id, created_at и updated_at - различны для каждой строки, применяя videos.uniq{|p| p.author}, где videos является ActiveRecord::Relation, включая все поля, вернет все строки в ActiveRecord::Relation.

Когда объект ActiveRecord::Relation имеет подмножество значений, uniq сможет определить различные значения из них.

Например: videos.select(:author).uniq.count даст 10 в вашем примере.

Разница между ActiveRecord::Relation#uniq и Array#uniq заключается в том, что версия Array принимает блок и использует возвращаемое значение блока для сравнения. Версия ActiveRecord:: Relation uniq просто игнорирует блок.