2013-03-21 21 views
8

Tôi muốn sử dụng một cái gì đó như find_in_batches, nhưng thay vì nhóm các đối tượng AR được tạo hoàn toàn tức thì, tôi muốn nhóm một thuộc tính nhất định, ví dụ: id. Vì vậy, về cơ bản, một hỗn hợp của việc sử dụng find_in_batchespluck:Đường ray: truy vấn thuộc tính theo đợt sử dụng AREL

Cars.where(:engine => "Turbo").pluck(:id).find_in_batches do |ids| 
    puts ids 
end 

# [1, 2, 3....] 
# ... 

Có cách nào để làm điều này (có thể với Arel) mà không cần phải viết OFFSET/LIMIT lý bản thân mình hoặc định kỳ để pagination đá quý như sẽ đánh số trang hoặc kaminari?

Trả lời

2

Đây không phải là giải pháp lý tưởng, nhưng đây là một phương pháp mà chỉ cần sao chép-bột nhão hầu hết find_in_batches nhưng mang lại một mối quan hệ thay vì một loạt các hồ sơ (chưa được kiểm tra) - chỉ khỉ vá nó vào Relation:

def in_batches(options = {}) 
    relation = self 

    unless arel.orders.blank? && arel.taken.blank? 
    ActiveRecord::Base.logger.warn("Scoped order and limit are ignored, it's forced to be batch order and batch size") 
    end 

    if (finder_options = options.except(:start, :batch_size)).present? 
    raise "You can't specify an order, it's forced to be #{batch_order}" if options[:order].present? 
    raise "You can't specify a limit, it's forced to be the batch_size" if options[:limit].present? 

    relation = apply_finder_options(finder_options) 
    end 

    start = options.delete(:start) 
    batch_size = options.delete(:batch_size) || 1000 

    relation = relation.reorder(batch_order).limit(batch_size) 
    relation = start ? relation.where(table[primary_key].gteq(start)) : relation 

    while (size = relation.size) > 0  

    yield relation 

    break if size < batch_size 

    primary_key_offset = relation.last.id 
    if primary_key_offset 
     relation = relation.where(table[primary_key].gt(primary_key_offset)) 
    else 
     raise "Primary key not included in the custom select clause" 
    end 
    end 
end 

với điều này, bạn sẽ có thể làm:

Cars.where(:engine => "Turbo").in_batches do |relation| 
    relation.pluck(:id) 
end 

đây không phải là việc thực hiện tốt nhất có thể (đặc biệt là liên quan đến primary_key_offset tính, mà instantiates một kỷ lục), nhưng bạn sẽ có được tinh thần.

+0

thực sự là một thử tốt. Nhưng tôi thích một giải pháp không phải khỉ, vì tôi muốn áp dụng logic đã nói trong một thư viện có thể được phân phối bởi một số dự án, và tôi muốn ít xâm phạm càng tốt liên quan đến việc tiêm mã trong AR . – ChuckE

+0

Điểm tốt ... vì vậy hãy biến nó trở thành một phương thức lớp học. Tôi đoán lib của bạn sẽ được bao gồm trong các mô hình anyway, và nó sẽ làm việc chỉ giống như miễn là AR được sử dụng. –

+0

Đã kết thúc bằng các phương thức AREL .limit và .offset. Tôi chỉ nói, thật tuyệt khi có một giải pháp out-of-the-box cho Rails. – ChuckE

Các vấn đề liên quan