web-dev-qa-db-fra.com

Rails filtrer un tableau d'objets par valeur d'attribut

Donc, je lance une requête sur la base de données et j’ai un tableau complet d’objets:

@attachments = Job.find(1).attachments

Maintenant que j’ai un tableau d’objets, je ne veux pas effectuer une autre requête de base de données, mais j’aimerais filtrer le tableau en fonction du file_type De l’objet Attachment afin que je puisse avoir une liste. de attachments où le type de fichier est 'logo', puis une autre liste de attachments où le type de fichier est 'image'

Quelque chose comme ça:

@logos  = @attachments.where("file_type = ?", 'logo')
@images = @attachments.where("file_type = ?", 'image')

Mais en mémoire au lieu d'une requête de base de données.

88
joepour

Essayez:

C'est bon :

@logos = @attachments.select { |attachment| attachment.file_type == 'logo' }
@images = @attachments.select { |attachment| attachment.file_type == 'image' }

mais pour des raisons de performances, vous n'avez pas besoin d'itérer @attachments deux fois:

@logos , @images = [], []
@attachments.each do |attachment|
  @logos << attachment if attachment.file_type == 'logo'
  @images << attachment if attachment.file_type == 'image'
end
163
Vik

Si vos pièces jointes sont

@attachments = Job.find(1).attachments

Ce sera un tableau d'objets d'attachement

Utilisez la méthode select pour filtrer en fonction du type_fichier.

@logos = @attachments.select { |attachment| attachment.file_type == 'logo' }
@images = @attachments.select { |attachment| attachment.file_type == 'image' }

Cela ne déclenchera aucune requête de base de données.

8

avez-vous essayé de charger avec impatience?

@attachments = Job.includes(:attachments).find(1).attachments
2

Je vais sur ce légèrement différemment. Structurez votre requête de manière à ne récupérer que ce dont vous avez besoin et à partir de là.

Alors faites votre requête comme suit:

#                                vv or Job.find(1) vv
attachments = Attachment.where(job_id: @job.id, file_type: ["logo", "image"])
# or 
Job.includes(:attachments).where(id: your_job_id, attachments: { file_type: ["logo", "image"] })

Et puis partitionnez les données:

@logos, @images = attachments.partition { |attachment| attachment.file_type == "logo" }

Cela vous permettra d'obtenir les données que vous recherchez de manière soignée et efficace.

0
SRack

Vous pouvez filtrer en utilisant où

Job.includes(:attachments).where(file_type: ["logo", "image"])
0
Darlan Dieterich