C’est donc plus une question d’arel qu’autre chose, mais voici ce que j’essaie de faire.
J'ai trois objets, disons, appelés Items
<Item id: 1, name: 'Book'>
<Item id: 2, name: 'Car'>
<Item id: 3, name: 'Book'>
Je souhaite effectuer une requête qui ne renverra qu'un seul de chaque attribut unique "name".
Quelque chose comme Item.select('distinct(name), items.*')
Cela ne fonctionne pas bien, il renvoie toujours les trois éléments.
Comment puis-je former cette requête afin qu'elle ne retourne que:
<Item id: 1, name: 'Book'>
<Item id: 2, name: 'Car'>
Si vous souhaitez récupérer le modèle entier tout en conservant l'unicité, vous pouvez utiliser ceci:
Item.select('distinct on (name) *')
Je n'ai testé cela qu'avec une base de données Postgres. Cela peut ou peut ne pas fonctionner avec mysql.
S'il vous plaît essayez ceci:
Item.select('distinct name')
Si vous avez seulement besoin d'un tableau avec les noms, sans l'ID, vous pouvez faire:
Item.pluck(:name).uniq
Résultat de la requête SQL:
#=> SELECT `items`.`name` FROM `items`
** modifier **
La uniq
est exécutée sur le tableau d'enregistrements. Faites attention si vous attendez beaucoup de disques. SQL Distinct est beaucoup plus rapide.
Si oui, utilisez la réponse de vee ci-dessus, avec un map
:
Item.select('distinct name').map(:name)
Dans Rails 4, essayez Items.all.to_a.uniq { |item| item.name }
Dans Rails 3, vous devriez pouvoir faire Items.uniq_by { |item| item.name }
Lorsque vous appelez uniq
sur un tableau, vous pouvez lui transmettre un bloc pour indiquer comment déterminer l'unicité. Dans Rails 3, vous pouviez utiliser uniq_by
, mais il est devenu obsolète dans Rails 4. Une méthode que j’ai trouvée consiste donc à convertir la relation ActiveRecord en un tableau et à appeler uniq
à ce sujet.
Ce qui suit est une requête ORM ORM qui produira le résultat souhaité avec toutes les dernières versions de Rails Rails 5.X.
@unique_values= []
Model.all.group_by(&:column_name).each do |key, val|
if val.count == 1
@unique_values << val
else
@unique_values << val.first
end
end
Pour Mysql, vous pouvez utiliser group
avec ONLY_FULL_GROUP_BY disabled,
Item.group(:name).to_sql
=> "SELECT `items`.* FROM `items` GROUP BY name"