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 vs where

Předání bloku do select s velkou sadou dat (tj. mnoha řádky) je pomalejší než použití jiných strategií, například where:

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ímco Model.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:

  1. dostatečně dotazovat přidruženou databázovou tabulku, aby…
  2. vygenerovat z přidružené tabulky pole se všemi cizími_klíči objektů z primární tabulky
  3. 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.

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna.