From 020b75cac8bc0125eb293d65b592fbff36a1cfdf Mon Sep 17 00:00:00 2001 From: wvengen Date: Sat, 4 Jun 2016 21:37:47 +0200 Subject: [PATCH] Fix group_orders document preloading --- app/documents/order_by_groups.rb | 40 +++++++++++++++++---- app/models/concerns/find_each_with_order.rb | 39 ++++++++++++++++++++ app/models/group_order.rb | 1 + 3 files changed, 74 insertions(+), 6 deletions(-) create mode 100644 app/models/concerns/find_each_with_order.rb diff --git a/app/documents/order_by_groups.rb b/app/documents/order_by_groups.rb index 02b9b93b..16a92238 100644 --- a/app/documents/order_by_groups.rb +++ b/app/documents/order_by_groups.rb @@ -1,26 +1,31 @@ # encoding: utf-8 class OrderByGroups < OrderPdf + # optimal value depends on the number of articles ordered on average by each + # ordergroup as well as the available memory + BATCH_SIZE = 50 + + attr_reader :order + def filename - I18n.t('documents.order_by_groups.filename', :name => @order.name, :date => @order.ends.to_date) + '.pdf' + I18n.t('documents.order_by_groups.filename', :name => order.name, :date => order.ends.to_date) + '.pdf' end def title - I18n.t('documents.order_by_groups.title', :name => @order.name, - :date => @order.ends.strftime(I18n.t('date.formats.default'))) + I18n.t('documents.order_by_groups.title', :name => order.name, + :date => order.ends.strftime(I18n.t('date.formats.default'))) end def body # Start rendering - @order.group_orders.ordered.each do |group_order| + each_group_order do |group_order| down_or_page 15 total = 0 rows = [] dimrows = [] - group_order_articles = group_order.group_order_articles.ordered - group_order_articles.each do |goa| + each_group_order_article_for(group_order) do |goa| price = goa.order_article.price.fc_price sub_total = price * goa.result total += sub_total @@ -65,4 +70,27 @@ class OrderByGroups < OrderPdf end end + + private + + def group_orders + order.group_orders.ordered. + joins(:ordergroup).order('groups.name'). + preload(:group_order_articles => {:order_article => [:article, :article_price]}) + end + + def each_group_order + group_orders.find_each_with_order(batch_size: BATCH_SIZE) {|go| yield go } + end + + def group_order_articles_for(group_order) + goas = group_order.group_order_articles.to_a + goas.sort_by!(&:id) + goas + end + + def each_group_order_article_for(group_order) + group_order_articles_for(group_order).each {|goa| yield goa } + end + end diff --git a/app/models/concerns/find_each_with_order.rb b/app/models/concerns/find_each_with_order.rb new file mode 100644 index 00000000..bbd21e96 --- /dev/null +++ b/app/models/concerns/find_each_with_order.rb @@ -0,0 +1,39 @@ +# @see https://gist.github.com/virtualstaticvoid/8705533 +module FindEachWithOrder + extend ActiveSupport::Concern + + class_methods do + + def find_each_with_order(options = {}) + find_in_batches_with_order(options) do |records| + records.each { |record| yield record } + end + end + + # NOTE: any limit() on the query is overridden with the batch size + def find_in_batches_with_order(options = {}) + options.assert_valid_keys(:batch_size) + + relation = self + + start = 0 + batch_size = options.delete(:batch_size) || 1000 + + relation = relation.limit(batch_size) + records = relation.offset(start).to_a + + while records.any? + records_size = records.size + + yield records + + break if records_size < batch_size + + # get the next batch + start += batch_size + records = relation.offset(start).to_a + end + end + + end +end diff --git a/app/models/group_order.rb b/app/models/group_order.rb index 4d5dd0ef..54b74811 100644 --- a/app/models/group_order.rb +++ b/app/models/group_order.rb @@ -1,5 +1,6 @@ # A GroupOrder represents an Order placed by an Ordergroup. class GroupOrder < ActiveRecord::Base + include FindEachWithOrder attr_accessor :group_order_articles_attributes