Column Down
select
a pluck
jsou dva různé a užitečné způsoby, jak vrátit hodnoty z jednoho nebo více sloupců v databázové tabulce jako kolekci. Představte si například, že máte v databázi tabulku questions
. Každá question
může mít tři pole: id
, question_text
a foreign_key
z přidružené tabulky. Chcete-li vrátit hodnoty pouze ze sloupce question_text
, použili byste select
nebo pluck
. Rád bych prozkoumal rozdíly mezi těmito dvěma metodami a na závěr uvedl aplikaci pluck
uvnitř aplikace Rails.
Select
select
funguje dvěma jedinečnými způsoby:
i.select
přebírá blok a funguje stejně jako Array#select
.
Model.all.select { |m| m.field == value }
Tento způsob sestaví z databáze pole objektů Ruby pro daný obor, převede je do pole a iteruje je pomocí Array#select
.
select
vswhere
Předání bloku do
select
s velkou sadou dat (tj. mnoha řádky) je pomalejší než použití jiných strategií, napříkladwhere
:
Model.where(field: value)
protože při použití
Model.all.select { |m| m.field == value }
Rails nejprve převede všechny řádky tabulky na objekty Ruby a poté spustí daný blok pro každý objekt Ruby, zatímcoModel.where(field: value)
vygeneruje příkaz SQL, který přenese těžkou práci na SQL, které je pro tento typ filtrování rychlejší než Ruby.
ii. select
upraví příkaz SELECT
pro dotaz SQL tak, aby se získala pouze určitá pole:
Model.select(:field)
# =>
Například z mého projektu:
Question.select(:question_text)
# => #<ActiveRecord::Relation >
Tím se vygeneruje následující SQL:
SELECT "questions"."question_text" FROM "questions"
Všimněte si prosím, že v tomto druhém příkladu metoda select
nevrací pole; vrací objekt ActiveRecord::Relation. V důsledku toho k ní můžete řetězit další metody ActiveRecord::QueryMethods. Například:
Question.select(:question_text).limit(5)# => #<ActiveRecord::Relation >
Tímto se vygeneruje následující SQL:
SELECT "questions"."question_text" FROM "questions" LIMIT ? ]
Pluck
Z příruček Rails:
pluck
lze použít k dotazování jednotlivých nebo více sloupců z podkladové tabulky modelu. Jako argument přijímá seznam názvů sloupců a vrací pole hodnot zadaných sloupců s odpovídajícím datovým typem.
Důležité je, že pluck
vrací pole. Nevrací objekt ActiveRecord::Relation jako select
. Takže například:
Question.pluck(:question_text)# => # this returns an array with all of the values from the question_text column from the questions table.
Protože pluck
převádí výsledek databázového dotazu na pole v jazyce Ruby bez konstrukce objektu ActiveRecord
, je výkonnější než select
.
To, že pluck
vrací pole, však znamená, že na pluck
nelze řetězit standardní dotazy ActiveRecord
. Pokud tak učiníte, vrátí NoMethodError
:
Question.pluck(:question_text).limit(5)# => NoMethodError: undefined method `limit' for #<Array:0x007fc5c1dfb3b0>
Ale pluck
funguje na objektech ActiveRecord
, takže následující příkaz vrátí očekávaný výsledek:
Question.limit(5).pluck(:question_text)#=>
pluck
může přijmout více argumentů a vytvořit vícerozměrné pole:
Question.pluck(:question_text, :course_id)#=> , , ...]
Kdy bych použil Pluck ?
Použil jsem pluck
k oboru ActiveRecord
modelových objektů, abych zjistil, které modelové objekty mají přidružené záznamy v jiné tabulce.
Příklad si vezměme následující třídu:
class Appointment < ActiveRecord::Base
has_many :chargesend
Pokud chceme zjistit, které appointments
mají charges
a které ne, můžeme použít pluck
v scope
. Zde je návod:
Nejprve si uvědomte, že pro Model.where(field: value)
může být value
buď jeden objekt (jako integer
, string
atd.), nebo to může být array
objektů.
Takže následující příkaz je platný a vrátí všechny appointments
s ids
, které jsou zahrnuty v poli.
Appointment.where(id: )# => returns all appointments with ids that are included in the array
Víme, že pluck
vrací pole, takže můžeme zkonstruovat pole, které obsahuje cizí klíče, které chceme zahrnout do oboru v přidruženém modelu. Chceme-li například zjistit, které appointments
mají přidružené charges
, můžeme vytvořit pole ze sloupce appointment_id
tabulky charges
takto:
Charge.pluck(:appointment_id)# => returns an array with all of the appointment_ids from the charges table, like:
Pro zjištění, které appointments
mají přidružené poplatky, můžeme napsat:
Appointment.where(id: Charge.pluck(:appointment_id))# this is the same as Appointment.where(id: )
A když to převedeme na obor na modelu Appointment
:
class Appointment < ActiveRecord::Base
has_many :charges scope :received_payment_info, -> {
where(id: Charge.pluck(:appointment_id)) }end
Takže nyní, když chceme určit, které appointments
mají přidružené charges
, můžeme napsat:
Appointment.received_payment_info#=> #<ActiveRecord::Relation
což nám vygeneruje následující dotazy SQL:
SELECT "charges"."appointment_id" FROM "charges"SELECT "appointments".* FROM "appointments" WHERE ("appointments"."id" IN (35, 44, 82) OR "appointments"."id" IS NULL)
pluck
umožnilo:
- dostatečně dotazovat přidruženou databázovou tabulku, aby…
- vygenerovat z přidružené tabulky pole se všemi cizími_klíči objektů z primární tabulky
- použít toto pole k určení, které objekty v primární tabulce mají přidružené objekty v sekundární tabulce
Doufám, že vám to pomohlo. Užijte si škubání a výběr.