82 votes

Comment récupérer les valeurs d'une seule colonne dans un tableau ?

Pour l'instant, je fais quelque chose comme ceci pour sélectionner une seule colonne de données :

points = Post.find_by_sql("select point from posts")

Ensuite, je les passe à une méthode, je voudrais que ma méthode reste agnostique, et je dois maintenant appeler hash.point à partir de ma méthode. Comment puis-je convertir rapidement ces données en un tableau et les transmettre à ma méthode, ou existe-t-il un meilleur moyen ?

192voto

alony Points 6018

Dans Rails 3.2, il existe un méthode de plumage pour cette

Comme ça :

Person.pluck(:id) # SELECT people.id FROM people
Person.pluck(:role).uniq # unique roles from array of people
Person.distinct.pluck(:role) # SELECT DISTINCT role FROM people SQL
Person.where(:confirmed => true).limit(5).pluck(:id)

Différence entre uniq et distinct

0 votes

Comment un tableau peut-il hériter de l'ordre des résultats d'une requête avec pluck ?

3 votes

Post.order(:score).pluck(:score) est la solution. Merci.

6 votes

Pour plumer les identités, il y a une méthode spéciale : Person.ids .

16voto

p11y Points 14785

Vous devez utiliser le pluck comme le suggère @alony. Si vous êtes bloqué avant Rails 3.2, vous pouvez utiliser la méthode ActiveRecord select ainsi que la méthode Array#map :

Post.select(:point).map(&:point)
#=> ["foo", "bar", "baz"] 

avant Ruby 1.9, vous deviez faire .map{|x| x.title} cependant, parce que Symbol#to_proc (remplacé par l'alias unaire & ) n'est pas défini dans les versions antérieures de Ruby.

0 votes

Merci. J'ai vu que vous avez commenté la nouvelle méthode Pluck. Pouvez-vous faire la même chose avec cette méthode ?

0 votes

Oui, si vous lisez attentivement la réponse de @alony, vous remarquerez qu'elle a déjà inclus un exemple qui fait cela.

5voto

Vik Points 2959

Si vous consultez la définition de select_values, vous verrez qu'elle utilise 'map(&:field_name)'.

  def select_values(arel, name = nil)
    result = select_rows(to_sql(arel), name)
    result.map { |v| v[0] }
  end

La façon commune et générale pour Rails de collecter les valeurs de tous les champs dans un tableau est la suivante :

points = Post.all(:select => 'point').map(&:point)

0 votes

Bon point. Je vous remercie. Cela fonctionne parfaitement et me permet d'appliquer l'ordre et d'autres éléments à la requête, contrairement à l'exemple de Post.select.

0 votes

Je ne suis pas d'accord avec vous, @franklinstine : Post.select(:point).limit(1) réalise SELECT point FROM "posts" LIMIT 1 alors que Post.all(:select => :point).limit(1) soulève un NoMethodError . Veuillez me corriger si je me trompe.

0 votes

Je suis d'accord avec vos commentaires. Mais je ne comprends pas où il est mentionné dans le post d'utiliser : Post.all(:select => :point).limit(1) Bien sûr, cela donnera une erreur "undefined method `limit'".

2voto

rajibchowdhury Points 1336
points = Post.all.collect {|p| p.point}

2 votes

Cela fonctionne, mais vous sélectionnez tous les champs de la base de données et vous filtrez ensuite le résultat en Ruby alors que la fonction select ne récupère que les colonnes spécifiées.

0voto

Muhammad Sannan Points 2541

Voir la partie "4 Sélection de champs spécifiques" de ce document. guide

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X