2013-03-21 1 views
8

Я бы хотел использовать что-то вроде find_in_batches, но вместо группировки полностью созданных объектов AR я хотел бы сгруппировать определенный атрибут, например, идентификатор. Таким образом, в основном, смесь с помощью find_in_batches и pluck:Рельсы: запрошенные атрибутные запросы с использованием AREL

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

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

Есть ли способ сделать это (возможно с Arel) без необходимости писать OFFSET логики/Ограничатся или повторяющимся в PAGINATION драгоценных камней, как отформатируют или Kaminari?

ответ

2

Это не идеальное решение, но вот метод, который просто скопировать пасты большинство find_in_batches но дает связь вместо массива записей (непроверенных) - просто обезьяна патч его в 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 

при этом, вы должны быть в состоянии сделать:

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

это не лучшая реализация возможно (особенно в отношении primary_key_offset расчета, который инстанцирует запись), но вы получите дух.

+0

Это была хорошая попытка, действительно. Но я предпочел бы использовать решение, не использующее обезьяну, поскольку я хочу применить указанную логику в библиотеке, которая может быть распределена несколькими проектами, и я хотел бы быть настолько менее навязчивым, насколько это возможно в отношении ввода кода в AR , – ChuckE

+0

Хорошая точка ... так что сделайте это методом класса. Я предполагаю, что ваш lib будет включен в модели в любом случае, и он должен работать так же, пока используется AR. –

+0

Закончен с использованием методов. ALIT и .offit. Я просто говорю, было бы неплохо иметь такое готовое решение для Rails. – ChuckE