From e2f7f32a60a7663d12b5dae0320f640150f354e7 Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Mon, 22 Aug 2016 15:48:31 -0300 Subject: Add support for Bitbucket pagination when fetching collections --- lib/bitbucket/collection.rb | 21 +++++++++++++++++++++ lib/bitbucket/page.rb | 36 ++++++++++++++++++++++++++++++++++++ lib/bitbucket/paginator.rb | 38 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 95 insertions(+) create mode 100644 lib/bitbucket/collection.rb create mode 100644 lib/bitbucket/page.rb create mode 100644 lib/bitbucket/paginator.rb (limited to 'lib/bitbucket') diff --git a/lib/bitbucket/collection.rb b/lib/bitbucket/collection.rb new file mode 100644 index 00000000000..9cc8947417c --- /dev/null +++ b/lib/bitbucket/collection.rb @@ -0,0 +1,21 @@ +module Bitbucket + class Collection < Enumerator + def initialize(paginator) + super() do |yielder| + loop do + paginator.next.each { |item| yielder << item } + end + end + + lazy + end + + def method_missing(method, *args) + return super unless self.respond_to?(method) + + self.send(method, *args) do |item| + block_given? ? yield(item) : item + end + end + end +end diff --git a/lib/bitbucket/page.rb b/lib/bitbucket/page.rb new file mode 100644 index 00000000000..ad9a2baba36 --- /dev/null +++ b/lib/bitbucket/page.rb @@ -0,0 +1,36 @@ +module Bitbucket + class Page + attr_reader :attrs, :items + + def initialize(raw, type) + @attrs = parse_attrs(raw) + @items = parse_values(raw, representation_class(type)) + end + + def next? + attrs.fetch(:next, false) + end + + def next + attrs.fetch(:next) + end + + private + + def parse_attrs(raw) + attrs = %w(size page pagelen next previous) + attrs.map { |attr| { attr.to_sym => raw[attr] } }.reduce(&:merge) + end + + def parse_values(raw, representation_class) + return [] if raw['values'].nil? || !raw['values'].is_a?(Array) + + raw['values'].map { |hash| representation_class.new(hash) } + end + + def representation_class(type) + class_name = "Bitbucket::Representation::#{type.to_s.camelize}" + class_name.constantize + end + end +end diff --git a/lib/bitbucket/paginator.rb b/lib/bitbucket/paginator.rb new file mode 100644 index 00000000000..a1672d9eaa1 --- /dev/null +++ b/lib/bitbucket/paginator.rb @@ -0,0 +1,38 @@ +module Bitbucket + class Paginator + PAGE_LENGTH = 50 # The minimum length is 10 and the maximum is 100. + + def initialize(connection, url, type) + @connection = connection + @type = type + @url = url + @page = nil + + connection.query(pagelen: PAGE_LENGTH, sort: :created_on) + end + + def next + raise StopIteration unless has_next_page? + + @page = fetch_next_page + @page.items + end + + private + + attr_reader :connection, :page, :url, :type + + def has_next_page? + page.nil? || page.next? + end + + def page_url + page.nil? ? url : page.next + end + + def fetch_next_page + parsed_response = connection.get(page_url) + Page.new(parsed_response, type) + end + end +end -- cgit v1.2.1