속성 값으로 객체 배열을 필터링하는 Rails


96

그래서 db에 대한 쿼리를 수행하고 완전한 객체 배열을 가지고 있습니다.

@attachments = Job.find(1).attachments

이제 객체 배열이 있으므로 다른 db 쿼리를 수행하고 싶지는 않지만 Attachment객체를 기반으로 배열을 필터링 하여 파일 유형이 어디에 있는지 file_type목록을 attachments얻은 'logo'다음 다른 위치 목록을 가질 수 있습니다 attachments. 파일 유형은'image'

이 같은:

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

그러나 db 쿼리 대신 메모리에 있습니다.


에 대한 좋은 유스 케이스처럼 보인다 partition- 여기 예 .
SRack

답변:


172

시도해보십시오 :

이건 괜찮아 :

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

그러나 성능을 위해 @attachments를 두 번 반복 할 필요가 없습니다.

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

2
@Vik의 솔루션이 매우 이상적이므로 바이너리의 경우 '파티션'기능을 사용하여 일을 달콤하게 만들 수 있습니다. ruby-doc.org/core-1.9.3/Enumerable.html#method-i-partition
Vlad

감사합니다 @Vlad, 멋지지만 객체에서 두 가지만 수집해야하는 경우에만 지원됩니다.
Vik

1
네, 그것이 제가 "바이너리"라고 말한 이유입니다. :). 질문에서 분명히 로고나 이미지의 선택이 있었기 때문에 완전성을 위해 이것을 추가했습니다.
Vlad

8

첨부 파일이

@attachments = Job.find(1).attachments

이것은 첨부 객체의 배열이 될 것입니다

select 메소드를 사용하여 file_type을 기준으로 필터링하십시오.

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

이것은 db 쿼리를 트리거하지 않습니다.


2

eager loading을 시도해 보셨습니까?

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

명확하지 않아 죄송합니다. 배열을 반복하지 않고 객체 속성 값으로 필터링하려면 어떻게해야합니까?
joepour

내가 올바르게 이해했다면 더 적은 db 쿼리를 원합니다. 특히 쿼리가 @attachments = Job.first.attachments실행되면 @attachments더 이상 db 쿼리를 원하지 않는 동안 루프를 원합니다 . 이것이 당신이하려는 일입니까?
Siwei Shen 申思维

DB 쿼리를 수행하고 개체 배열을받습니다. 그런 다음 속성 값을 기준으로 객체를 필터링하여 하나의 배열에서 두 개의 개별 목록을 만들고 싶습니다 (원래 게시물 참조)
-cheers

0

where를 사용하여 필터링 할 수 있습니다.

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

0

나는 이것에 대해 약간 다르게 할 것입니다. 필요한 항목 만 검색하고 여기에서 분할하도록 쿼리를 구성합니다.

따라서 쿼리를 다음과 같이 만드십시오.

#                                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"] })

그런 다음 데이터를 분할합니다.

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

그러면 깔끔하고 효율적인 방식으로 원하는 데이터를 얻을 수 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.