select en pluck zijn twee verschillende en nuttige manieren om de waarden van een of meer kolommen in een databasetabel als een verzameling terug te geven. Bijvoorbeeld, stel u heeft een questions tabel in uw database. Elke question zou drie velden kunnen hebben: id, question_text, en een foreign_key uit een bijbehorende tabel. Om de waarden van alleen de kolom question_text terug te geven, zou u select of pluck gebruiken. Ik wil graag de verschillen tussen deze twee methoden verkennen en eindigen met een toepassing van pluck binnen een Rails applicatie.

Select

select werkt op twee unieke manieren:

i.select neemt een blok en werkt net als Array#select.

Model.all.select { |m| m.field == value }

Dit bouwt een array van Ruby objecten uit de database voor het bereik, converteert ze in een array en itereert er doorheen met Array#select.

select vs where

Het invoeren van een blok in select met een grote gegevensverzameling (d.w.z. veel rijen) is langzamer dan het gebruik van andere strategieën, zoals where:

Model.where(field: value)

omdat met Model.all.select { |m| m.field == value }, Rails eerst alle tabelrijen zal omzetten in Ruby objecten, en dan het gegeven blok voor elk Ruby object zal uitvoeren, terwijl Model.where(field: value) een SQL verklaring genereert die het zware werk aan SQL uit handen geeft, wat sneller is dan Ruby voor dit type filtering.

ii. select wijzigt het SELECT statement voor de SQL query zodat alleen bepaalde velden worden opgehaald:

Model.select(:field)
# =>

Voorbeeld, van een project van mij:

Question.select(:question_text)
# => #<ActiveRecord::Relation >

Dit genereert de volgende SQL:

SELECT "questions"."question_text" FROM "questions"

Merk op dat in dit tweede voorbeeld, de select methode geen array retourneert; het retourneert een ActiveRecord::Relation object. Als gevolg daarvan kunt u er andere ActiveRecord::QueryMethods aan koppelen. Bijvoorbeeld:

Question.select(:question_text).limit(5)# => #<ActiveRecord::Relation >

Dit genereert de volgende SQL:

SELECT "questions"."question_text" FROM "questions" LIMIT ? ]

Pluk

Uit de Rails Guides:

pluck kan worden gebruikt om query’s uit te voeren op enkele of meerdere kolommen uit de onderliggende tabel van een model. Het accepteert een lijst met kolomnamen als argument en retourneert een array met waarden van de opgegeven kolommen met het bijbehorende gegevenstype.

Het belangrijke punt hier is dat pluck een array retourneert. Het retourneert geen ActiveRecord::Relation-object, zoals select. Dus, bijvoorbeeld:

Question.pluck(:question_text)# => # this returns an array with all of the values from the question_text column from the questions table.

Omdat pluck het resultaat van een database query omzet in een Ruby array zonder een ActiveRecord object te construeren, is het performanter dan select.

Dat pluck een array retourneert, betekent echter dat je geen standaard ActiveRecord queries kunt koppelen aan pluck. Dit zal een NoMethodError opleveren:

Question.pluck(:question_text).limit(5)# => NoMethodError: undefined method `limit' for #<Array:0x007fc5c1dfb3b0>

Maar pluck werkt wel op ActiveRecord objecten, dus het volgende zal het verwachte resultaat opleveren:

Question.limit(5).pluck(:question_text)#=> 

pluck kan meerdere argumenten aannemen om een multidimensionale array te construeren:

Question.pluck(:question_text, :course_id)#=> , , ...]

Wanneer zou ik Pluck gebruiken?

Ik heb pluck gebruikt om ActiveRecord modelobjecten te scopen om te bepalen welke modelobjecten geassocieerde records in een andere tabel hebben.

Neem bijvoorbeeld de volgende klasse:

class Appointment < ActiveRecord::Base
has_many :chargesend

Als we willen bepalen welke appointments charges hebben en welke niet, kunnen we pluck in een scope gebruiken. Hier is hoe:

Vooreerst, onthoud dat voor Model.where(field: value), value ofwel een enkel object kan zijn (zoals integer, string, enz.), of het kan een array van objecten zijn.

Dus, het volgende is geldig en zal alle appointments met ids teruggeven die in de array zijn opgenomen.

Appointment.where(id: )# => returns all appointments with ids that are included in the array

Wel, we weten dat pluck een array retourneert, dus kunnen we een array construeren die de foreign keys bevat die we willen scopen in het bijbehorende model. Als we bijvoorbeeld willen bepalen welke appointments charges hebben geassocieerd, kunnen we een array maken van de appointment_id kolom van de charges tabel, zoals dit:

Charge.pluck(:appointment_id)# => returns an array with all of the appointment_ids from the charges table, like: 

Om te bepalen welke appointments kosten hebben geassocieerd, kunnen we schrijven:

Appointment.where(id: Charge.pluck(:appointment_id))# this is the same as Appointment.where(id: )

En dit omzetten in een scope op het Appointment model:

class Appointment < ActiveRecord::Base
has_many :charges scope :received_payment_info, -> {
where(id: Charge.pluck(:appointment_id)) }end

Wanneer we nu dus willen bepalen welke appointments geassocieerde charges hebben, kunnen we schrijven:

Appointment.received_payment_info#=> #<ActiveRecord::Relation 

wat de volgende SQL queries genereert:

SELECT "charges"."appointment_id" FROM "charges"SELECT "appointments".* FROM "appointments" WHERE ("appointments"."id" IN (35, 44, 82) OR "appointments"."id" IS NULL)

pluck waarmee we:

  1. efficiënt een geassocieerde databasetabel te bevragen om…
  2. een array te genereren uit de geassocieerde tabel met alle foreign_keys van objecten uit de primaire tabel
  3. die array te gebruiken om te bepalen welke objecten in de primaire tabel geassocieerde objecten hebben in de secundaire tabel

Ik hoop dat je dit nuttig vond. Veel plezier met plukken en selecteren.

Geef een antwoord

Het e-mailadres wordt niet gepubliceerd.