stripe-ruby/lib/stripe/list_object.rb
Brandur 0311b4a7cd Fix reference to URLs on ListObject
In #394 we renamed `url` to `resource_url` in order to prevent name
collisions in API resource that also have a `url` property.
Unfortunately, this didn't account for the fact that when making API
calls on a list object we rely on a returned `url` property to build a
request, and this had been renamed to `resource_url`. Test should have
caught this, but they were written to work differently than how live
API calls actually function.

This patch repairs the problem by adding a `resource_url` to list
objects, and modifies test to be more accurate to reality so that
they'll catch this class of problem in the future.

Fixes #395.
2016-03-14 06:52:26 -07:00

106 lines
3.3 KiB
Ruby

module Stripe
class ListObject < StripeObject
include Enumerable
include Stripe::APIOperations::List
include Stripe::APIOperations::Request
include Stripe::APIOperations::Create
# This accessor allows a `ListObject` to inherit various filters that were
# given to a predecessor. This allows for things like consistent limits,
# expansions, and predicates as a user pages through resources.
attr_accessor :filters
# An empty list object. This is returned from +next+ when we know that
# there isn't a next page in order to replicate the behavior of the API
# when it attempts to return a page beyond the last.
def self.empty_list(opts={})
ListObject.construct_from({ :data => [] }, opts)
end
def initialize(*args)
super
self.filters = {}
end
def [](k)
case k
when String, Symbol
super
else
raise ArgumentError.new("You tried to access the #{k.inspect} index, but ListObject types only support String keys. (HINT: List calls return an object with a 'data' (which is the data array). You likely want to call #data[#{k.inspect}])")
end
end
# Iterates through each resource in the page represented by the current
# `ListObject`.
#
# Note that this method makes no effort to fetch a new page when it gets to
# the end of the current page's resources. See also +auto_paging_each+.
def each(&blk)
self.data.each(&blk)
end
# Iterates through each resource in all pages, making additional fetches to
# the API as necessary.
#
# Note that this method will make as many API calls as necessary to fetch
# all resources. For more granular control, please see +each+ and
# +next_page+.
def auto_paging_each(&blk)
return enum_for(:auto_paging_each) unless block_given?
page = self
loop do
page.each(&blk)
page = page.next_page
break if page.empty?
end
end
# Returns true if the page object contains no elements.
def empty?
self.data.empty?
end
def retrieve(id, opts={})
id, retrieve_params = Util.normalize_id(id)
response, opts = request(:get,"#{resource_url}/#{CGI.escape(id)}", retrieve_params, opts)
Util.convert_to_stripe_object(response, opts)
end
# Fetches the next page in the resource list (if there is one).
#
# This method will try to respect the limit of the current page. If none
# was given, the default limit will be fetched again.
def next_page(params={}, opts={})
return self.class.empty_list(opts) if !has_more
last_id = data.last.id
params = filters.merge({
:starting_after => last_id,
}).merge(params)
list(params, opts)
end
# Fetches the previous page in the resource list (if there is one).
#
# This method will try to respect the limit of the current page. If none
# was given, the default limit will be fetched again.
def previous_page(params={}, opts={})
first_id = data.first.id
params = filters.merge({
:ending_before => first_id,
}).merge(params)
list(params, opts)
end
def resource_url
self.url ||
raise(ArgumentError, "List object does not contain a 'url' field.")
end
end
end