gitlab-org--gitlab-foss/lib/gitlab/multi_collection_paginator.rb
blackst0ne 0e9297b37a [Rails5] Fix per_page in lib/gitlab/multi_collection_paginator.rb
In Rails 5 the `per_page` argument came from `params` is String but an
Integer is expected.

This commit explicitly converts `per_page` to an Integer.
It fixes the errors like:

```
  1) Groups::ChildrenController GET #index for subgroups filtering children succeeds if multiple pages contain matching subgroups
     Failure/Error:
       hash[page] = second_collection.page(second_collection_page)
                      .per(per_page - paginated_first_collection(page).size)
                      .padding(offset)

     NoMethodError:
       undefined method `-' for "3":String
       Did you mean?  -@
     # ./lib/gitlab/multi_collection_paginator.rb:42:in `block in paginated_second_collection'
     # ./lib/gitlab/multi_collection_paginator.rb:46:in `paginated_second_collection'
     # ./lib/gitlab/multi_collection_paginator.rb:14:in `paginate'
     # ./app/finders/group_descendants_finder.rb:52:in `children'
     # ./app/finders/group_descendants_finder.rb:34:in `execute'
     # ./app/controllers/groups/children_controller.rb:36:in `setup_children'
     # ./app/controllers/groups/children_controller.rb:18:in `index'
     # ./lib/gitlab/i18n.rb:50:in `with_locale'
     # ./lib/gitlab/i18n.rb:56:in `with_user_locale'
     # ./app/controllers/application_controller.rb:351:in `set_locale'
     # ./spec/controllers/groups/children_controller_spec.rb:182:in `block (5 levels) in <top (required)>'
     # ./spec/spec_helper.rb:198:in `block (2 levels) in <top (required)>'
```
2018-05-11 13:36:38 +11:00

64 lines
2 KiB
Ruby

module Gitlab
class MultiCollectionPaginator
attr_reader :first_collection, :second_collection, :per_page
def initialize(*collections, per_page: nil)
raise ArgumentError.new('Only 2 collections are supported') if collections.size != 2
@per_page = (per_page || Kaminari.config.default_per_page).to_i
@first_collection, @second_collection = collections
end
def paginate(page)
page = page.to_i
paginated_first_collection(page) + paginated_second_collection(page)
end
def total_count
@total_count ||= first_collection.size + second_collection.size
end
private
def paginated_first_collection(page)
@first_collection_pages ||= Hash.new do |hash, page|
hash[page] = first_collection.page(page).per(per_page)
end
@first_collection_pages[page]
end
def paginated_second_collection(page)
@second_collection_pages ||= Hash.new do |hash, page|
second_collection_page = page - first_collection_page_count
offset = if second_collection_page < 1 || first_collection_page_count.zero?
0
else
per_page - first_collection_last_page_size
end
hash[page] = second_collection.page(second_collection_page)
.per(per_page - paginated_first_collection(page).size)
.padding(offset)
end
@second_collection_pages[page]
end
def first_collection_page_count
return @first_collection_page_count if defined?(@first_collection_page_count)
first_collection_page = paginated_first_collection(0)
@first_collection_page_count = first_collection_page.total_pages
end
def first_collection_last_page_size
return @first_collection_last_page_size if defined?(@first_collection_last_page_size)
@first_collection_last_page_size = paginated_first_collection(first_collection_page_count)
.except(:select)
.size
end
end
end