web-dev-qa-db-fra.com

Rails: la manière correcte d’activer relation d’enregistrement vers tableau?

J'essayais de sélectionner des objets uniq par un attribut, en utilisant @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 n'est pas pour ActiveRecord_Relation. Et le problème est que la requête renvoie un Video::ActiveRecord_Relation, mais il me faut array.

Ceci pourrait certainement être réalisé en utilisant to_a, mais est-ce élégant?

  1. Quelle est la bonne façon de gérer cela?
  2. Est-il possible d'utiliser .uniq pour activerecord:relation?
41
cqcn1991

Si vous devez accéder au résultat de la requête, utilisez simplement #to_a sur l'instance ActiveRecord :: Relation.

Sur guides Rails , vous pouvez trouver des modifications importantes sur Rails 4.0: "Model.all renvoie désormais une ActiveRecord :: Relation, plutôt qu'un tableau d'enregistrements. Utilisez Relation #to_a si vous voulez vraiment un tableau. Dans certains cas, cela peut causer une panne lors de la mise à jour. "Ceci est valable pour d'autres méthodes de relation telles que: où.

 selected_videos = videos.to_a.uniq{|p| p.author}
46
Alejandro Babio

.uniq N'a pas beaucoup de sens quand il est appliqué à l'ensemble de l'enregistrement actif.

Étant donné qu'au moins un des trois attributs - id, created_at Et updated_at - est différent pour chaque ligne, appliquant videos.uniq{|p| p.author}videos est un ActiveRecord::Relation incluant tous les champs, retournera toutes les lignes du ActiveRecord::Relation.

Lorsque l'objet ActiveRecord::Relation Comporte un sous-ensemble de valeurs, uniq pourra en déterminer les valeurs distinctes.

Par exemple: videos.select(:author).uniq.count donnera 10 dans votre exemple.

La différence entre ActiveRecord::Relation#uniq Et Array#uniq Réside dans le fait que la version Array accepte un bloc et utilise la valeur de retour d'un bloc à des fins de comparaison. La version ActiveRecord :: Relation de uniq ignore simplement le bloc.

3
Prakash Murthy