Skip to content

Instantly share code, notes, and snippets.

@mgreenly
Last active March 9, 2020 21:44
Show Gist options
  • Save mgreenly/6d3e692930384e18fab2ef82fb2498db to your computer and use it in GitHub Desktop.
Save mgreenly/6d3e692930384e18fab2ef82fb2498db to your computer and use it in GitHub Desktop.
# inherit from Enumerator
class Pager1 < Enumerator
def initialize(url, page_size: 100, max_pages: Float::INFINITY, first_page: 0)
@url = url
super() do |receiver|
page = first_page
pages = []
while page < (first_page + max_pages)
get(page, page_size).each do |row|
receiver.yield row
end
page += 1
end
end
end
# this simulates fetching a page of results from the url
def get(page, size)
puts "getting page #{page}" # some debug output to demonstrate this is done lazy
(page * size)..(page * size + (size - 1))
end
end
# done without inheritance
class Pager2
attr_reader :url, :page_size, :max_pages, :first_page
def initialize(url, page_size: 100, max_pages: Float::INFINITY, first_page: 0)
@url = url
@page_size = page_size
@max_pages = max_pages
@first_page = first_page
end
def each
return enum_for(:each) unless block_given?
page = first_page
pages = []
while page < (first_page + max_pages)
get(page, page_size).each do |row|
yield row
end
page += 1
end
end
private
# this simulates fetching a page of results from the url
def get(page, size)
puts "getting page #{page}" # some debug output to demonstrate this is done lazy
(page * size)..(page * size + (size - 1))
end
end
# same as pager2 but includes enumerable
class Pager3
include Enumerable
attr_reader :url, :page_size, :max_pages, :first_page
def initialize(url, page_size: 100, max_pages: Float::INFINITY, first_page: 0)
@url = url
@page_size = page_size
@max_pages = max_pages
@first_page = first_page
end
def each
return enum_for(:each).lazy unless block_given?
page = first_page
pages = []
while page < (first_page + max_pages)
get(page, page_size).each do |row|
yield row
end
page += 1
end
end
private
# this simulates fetching a page of results from the url
def get(page, size)
puts "getting page #{page}" # some debug output to demonstrate this is done lazy
(page * size)..(page * size + (size - 1))
end
end
#
# Demonstrate both
#
pager = Pager1.new('url', page_size: 3, max_pages: 9, first_page: 1).lazy
pp pager.each.drop(4).take(2).to_a
puts
pager = Pager2.new('url', page_size: 3, max_pages: 9, first_page: 1)
pp pager.each.lazy.drop(4).take(2).to_a
puts
pager = Pager3.new('url', page_size: 3, max_pages: 9, first_page: 1)
pp pager.drop(4).take(2).to_a
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment