So erhalten Sie die Werte einer einzelnen Spalte in ein Array


79

Im Moment mache ich so etwas, um eine einzelne Datenspalte auszuwählen:

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

Wenn ich sie dann an eine Methode übergebe, möchte ich, dass meine Methode agnostisch bleibt und jetzt hash.point aus meiner Methode heraus aufrufen muss. Wie kann ich dies schnell in ein Array konvertieren und den Datensatz an meine Methode übergeben, oder gibt es einen besseren Weg?

Antworten:


189

In Rails 3.2 gibt es eine zupfen Methode für diese

Genau wie dieser:

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)

Unterschied zwischen einzigartig und verschieden


Wie kann ein Array die Reihenfolge eines Abfrageergebnisses mit Zupfen erben?
Franklin Stine

3
Post.order (: score) .pluck (: score) ist die Lösung. Vielen Dank.
Franklin Stine

6
Zum Zupfen von IDs gibt es eine spezielle Methode : Person.ids.
Schock_one

Schauen Sie sich auch Ernie Millers Juwel Valium github.com/ernie/valium an, besonders wenn Sie auf einer älteren Schiene sind oder mehrere Spalten möchten
James Daniels

Ab Rails 5.0 wird jetzt empfohlen, distinctanstelle von uniq: soPerson.distinct.pluck(:role)
David

15

Sie sollten die pluckMethode wie von @alony vorgeschlagen verwenden. Wenn Sie vor Rails 3.2 nicht weiterkommen, können Sie die ActiveRecord- selectMethode zusammen mit Array#mapfolgenden Methoden verwenden :

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

vor Ruby 1.9 müssten Sie dies jedoch tun .map{|x| x.title}, da Symbol#to_proc(Aliasing durch den unären &Operator) in früheren Versionen von Ruby nicht definiert ist.


Vielen Dank. Ich habe gesehen, dass Sie die neue Zupfmethode kommentiert haben. Kannst du das auch so machen?
Franklin Stine

Ja, wenn Sie die Antwort von @ alony sorgfältig lesen, werden Sie feststellen, dass sie bereits ein Beispiel beigefügt hat, das dies tut.
Patrick Oscity

5

Wenn Sie die Definition von select_values ​​sehen, verwenden Sie 'map (&: field_name)'.

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

Die allgemeine und allgemeine Rails-Methode zum Sammeln aller Feldwerte im Array lautet wie folgt:

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

Guter Punkt. Vielen Dank. Dies funktioniert hervorragend und ermöglicht es mir, im Gegensatz zum Post.select-Beispiel weiterhin die Reihenfolge und andere Dinge auf die Abfrage anzuwenden.
Franklin Stine

Ich stimme dir nicht zu, @franklinstine: Post.select(:point).limit(1)führt aus, SELECT point FROM "posts" LIMIT 1während Post.all(:select => :point).limit(1)a NoMethodError. Bitte korrigieren Sie mich, falls ich falsch liege.
Patrick Oscity

Ich stimme Ihren Kommentaren zu. Aber ich bekomme nicht, wo in dem Beitrag erwähnt wird, um zu verwenden: Post.all (: select =>: point) .limit (1) Natürlich wird es Fehler "undefinierte Methode` limit '"geben
Vik

@franklinstine sagte, dass er Ihre Methode bevorzugt, weil er andere Aussagen danach verketten könnte, ich wollte nur
klarstellen

Ja @padde du hast falsch gefolgert. Ich sagte, Sie können weiterhin Order- und andere Abfrageanweisungen anwenden, z. B.: Post.all (: select => 'score' ,: order => 'score ASC'). Map (&: score).
Franklin Stine

2
points = Post.all.collect {|p| p.point}

2
Dies funktioniert, aber Sie wählen alle Felder aus der Datenbank aus und filtern das Ergebnis in Ruby, während die selectAnweisung nur die angegebenen Spalten abruft.
Patrick Oscity
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.