Rails lọc mảng đối tượng theo giá trị thuộc tính


95

Vì vậy, tôi thực hiện một truy vấn tới db và tôi có một mảng hoàn chỉnh các đối tượng:

@attachments = Job.find(1).attachments

Bây giờ tôi có một mảng của các đối tượng Tôi không muốn thực hiện một truy vấn db, nhưng tôi muốn lọc mảng dựa trên Attachmentđối tượng là file_typeđể tôi có thể có một danh sách các attachmentsnơi mà các loại tập tin là 'logo'rồi một danh sách các attachmentsnơi loại tệp là'image'

Một cái gì đó như thế này:

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

Nhưng trong bộ nhớ thay vì một truy vấn db.


Có vẻ như một trường hợp sử dụng tốt cho partition- ví dụ ở đây .
SRack

Câu trả lời:


172

Thử :

Điều này là tốt:

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

nhưng để có hiệu suất khôn ngoan, bạn không cần phải lặp lại @attachments hai lần:

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

2
Vì giải pháp của @ Vik khá lý tưởng, tôi chỉ nói thêm rằng trong trường hợp nhị phân, bạn có thể sử dụng hàm 'phân vùng' để làm cho mọi thứ trở nên ngọt ngào. ruby-doc.org/core-1.9.3/Enumerable.html#method-i-partition
Vlad

Cảm ơn @Vlad, điều đó thật tuyệt, nhưng nó chỉ hỗ trợ nếu chúng ta chỉ cần thu thập hai thứ từ đối tượng.
Vik

1
Vâng, đó là lý do tại sao tôi nói "nhị phân" :). Trong câu hỏi, rõ ràng là có một sự lựa chọn về logo hoặc hình ảnh, vì vậy tôi đã thêm điều này cho hoàn chỉnh.
Vlad

8

Nếu tệp đính kèm của bạn là

@attachments = Job.find(1).attachments

Đây sẽ là mảng các đối tượng đính kèm

Sử dụng phương pháp chọn để lọc dựa trên loại_tệp.

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

Điều này sẽ không kích hoạt bất kỳ truy vấn db nào.


2

bạn đã thử tải háo hức chưa?

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

Xin lỗi, tôi không hiểu rõ: làm cách nào để lọc theo giá trị của thuộc tính đối tượng mà không cần lặp qua mảng?
joepour

Nếu tôi hiểu đúng, bạn muốn truy vấn db ít hơn, đặc biệt, khi một truy vấn chẳng hạn như được @attachments = Job.first.attachmentsthực thi, bạn muốn lặp lại @attachmentstrong khi bạn không muốn có thêm truy vấn db nào nữa. đây có phải là những gì bạn muốn làm?
Siwei Shen 申思维

Tôi thực hiện một truy vấn db và nhận được một mảng các đối tượng. Sau đó tôi muốn tạo ra hai danh sách riêng biệt từ đó một mảng bằng cách lọc các đối tượng dựa trên giá trị của các thuộc tính của họ (Xem bài đăng gốc) - cổ vũ
joepour

0

Bạn có thể lọc bằng cách sử dụng

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

0

Tôi sẽ đi về điều này hơi khác một chút. Cấu trúc truy vấn của bạn để chỉ lấy những gì bạn cần và tách từ đó.

Vì vậy, hãy thực hiện truy vấn của bạn như sau:

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

Và sau đó phân vùng dữ liệu:

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

Điều đó sẽ nhận được dữ liệu bạn đang theo dõi một cách gọn gàng và hiệu quả.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.