14

Bối cảnh

Tôi có ứng dụng đường ray với các liên kết lồng nhau sâu.Kết nối tải theo yêu cầu với Bộ nối tiếp mô hình hoạt động

      .-< WorkPeriod 
Timecard -< Week -< Day -<--< Subtotal 
          `-< Adjustment 

-< (has many) 

Tôi đang sử dụng Active Model Serializer để xây dựng API.

Về phía khách hàng, tôi muốn tải một timecard và tất cả các liên kết của nó trong một lần chụp.

Hiện nay serializers của tôi trông như thế này,

class TimecardSerializer < ActiveModel::Serializer 
    embed :ids, include: true 
    has_many :weeks 
end 
class WeekSerializer < ActiveModel::Serializer 
    embed :ids, include: true 
    has_many :days 
end 
# ... etc ... 

Vấn đề

này tất cả các công trình tìm kiếm, ngoại trừ không có gì trở nên háo hức-nạp. Vì vậy, nó kết thúc lên thực hiện rất nhiều cuộc gọi đến cơ sở dữ liệu cho mỗi yêu cầu. Đối với mỗi tuần, nó làm cho một yêu cầu riêng biệt cho những ngày trong tuần đó. Và cho mỗi ngày, nó tạo ra một yêu cầu riêng biệt cho các khoảng thời gian làm việc, tổng phụ và điều chỉnh của nó.

Trả lời

9

Một giải pháp là xác định phương thức weeks của riêng bạn trên TimecardSerializer. Từ đó bạn có thể .includes() tất cả các liên kết bạn muốn tải mong muốn.

class TimecardSerializer < ActiveModel::Serializer 
    embed :ids, include: true 
    has_many :weeks 

    def weeks 
    object.weeks.includes(days: [:sub_totals, :work_periods, :adjustments]) 
    end 
end 

Mọi truy vấn sẽ vẫn hiển thị trong nhật ký nhưng hầu hết sẽ là truy vấn được lưu trong bộ nhớ cache thay vì truy vấn thực.

+1

Điều này là tốt để tải một tài nguyên, nhưng sẽ không hoạt động nếu bộ nối tiếp này được sử dụng để trả về danh sách 'Timecard's. Đặc biệt, 'tuần' sẽ không được tải háo hức, mặc dù các liên kết' tuần' sẽ là. – hjdivad

8

Tôi gặp sự cố tương tự. Tôi đã sửa nó trong bộ điều khiển của mình. Tôi thích ý tưởng đặt nó trong serializer, nhưng có nó trong bộ điều khiển bắt vấn đề n + 1 tuần được tạo ra bởi các ArraySerializer quá.

Timecard.find(params[:id]).includes(weeks: [{ days: [:sub_totals, :work_periods, :adjustments] }]) 

Timecard.includes(weeks: [{ days: [:sub_totals, :work_periods, :adjustments] }]) 

nên tải tại háo hức và hạn chế truy vấn để chỉ sáu hit db.