Merge pull request #394 from shekibobo/feature/resource-url

Fix ApiResource resource URL clashing with user-defined URL properties. Fixes #393.
This commit is contained in:
Brandur 2016-03-11 11:23:00 -08:00
commit f612aa9057
33 changed files with 93 additions and 106 deletions

View File

@ -5,7 +5,7 @@ module Stripe
extend Stripe::APIOperations::List
include Stripe::APIOperations::Update
def url
def resource_url
if self['id']
super
else
@ -25,7 +25,6 @@ module Stripe
opts = id
id = nil
end
super(id, opts)
end

View File

@ -2,7 +2,7 @@ module Stripe
module APIOperations
module Create
def create(params={}, opts={})
response, opts = request(:post, url, params, opts)
response, opts = request(:post, resource_url, params, opts)
Util.convert_to_stripe_object(response, opts)
end
end

View File

@ -3,7 +3,7 @@ module Stripe
module Delete
def delete(params={}, opts={})
opts = Util.normalize_opts(opts)
response, opts = request(:delete, url, params, opts)
response, opts = request(:delete, resource_url, params, opts)
initialize_from(response, opts)
end
end

View File

@ -5,7 +5,7 @@ module Stripe
opts = Util.normalize_opts(opts)
opts = @opts.merge(opts) if @opts
response, opts = request(:get, url, filters, opts)
response, opts = request(:get, resource_url, filters, opts)
obj = ListObject.construct_from(response, opts)
# set filters so that we can fetch the same limit, expansions, and

View File

@ -14,9 +14,6 @@ module Stripe
# in the list, it overrides the update URL used for the create or
# update.
def save(params={})
# Let the caller override the URL but avoid serializing it.
req_url = params.delete(:req_url) || save_url
# We started unintentionally (sort of) allowing attributes sent to
# +save+ to override values used during the update. So as not to break
# the API, this makes that official here.
@ -31,7 +28,7 @@ module Stripe
# generated a uri for this object with an identifier baked in
values.delete(:id)
response, opts = request(:post, req_url, values)
response, opts = request(:post, save_url, values)
initialize_from(response, opts)
self
@ -47,9 +44,9 @@ module Stripe
# resource. Otherwise, generate a URL based on the object's identifier
# for a normal update.
if self[:id] == nil && self.class.respond_to?(:create)
self.class.url
self.class.resource_url
else
url
resource_url
end
end
end

View File

@ -6,22 +6,22 @@ module Stripe
self.name.split('::')[-1]
end
def self.url
def self.resource_url
if self == APIResource
raise NotImplementedError.new('APIResource is an abstract class. You should perform actions on its subclasses (Charge, Customer, etc.)')
end
"/v1/#{CGI.escape(class_name.downcase)}s"
end
def url
def resource_url
unless id = self['id']
raise InvalidRequestError.new("Could not determine which URL to request: #{self.class} instance has invalid ID: #{id.inspect}", 'id')
end
"#{self.class.url}/#{CGI.escape(id)}"
"#{self.class.resource_url}/#{CGI.escape(id)}"
end
def refresh
response, opts = request(:get, url, @retrieve_params)
response, opts = request(:get, resource_url, @retrieve_params)
initialize_from(response, opts)
end

View File

@ -2,7 +2,7 @@ module Stripe
class ApplicationFee < APIResource
extend Stripe::APIOperations::List
def self.url
def self.resource_url
'/v1/application_fees'
end

View File

@ -3,8 +3,8 @@ module Stripe
include Stripe::APIOperations::Update
extend Stripe::APIOperations::List
def url
"#{ApplicationFee.url}/#{CGI.escape(fee)}/refunds/#{CGI.escape(id)}"
def resource_url
"#{ApplicationFee.resource_url}/#{CGI.escape(fee)}/refunds/#{CGI.escape(id)}"
end
def self.retrieve(id, api_key=nil)

View File

@ -2,7 +2,7 @@ module Stripe
class BalanceTransaction < APIResource
extend Stripe::APIOperations::List
def self.url
def self.resource_url
'/v1/balance/history'
end
end

View File

@ -5,15 +5,15 @@ module Stripe
extend Stripe::APIOperations::List
def verify(params={}, opts={})
response, opts = request(:post, url + '/verify', params, opts)
response, opts = request(:post, resource_url + '/verify', params, opts)
initialize_from(response, opts)
end
def url
def resource_url
if respond_to?(:customer)
"#{Customer.url}/#{CGI.escape(customer)}/sources/#{CGI.escape(id)}"
"#{Customer.resource_url}/#{CGI.escape(customer)}/sources/#{CGI.escape(id)}"
elsif respond_to?(:account)
"#{Account.url}/#{CGI.escape(account)}/external_accounts/#{CGI.escape(id)}"
"#{Account.resource_url}/#{CGI.escape(account)}/external_accounts/#{CGI.escape(id)}"
end
end

View File

@ -5,15 +5,15 @@ module Stripe
include Stripe::APIOperations::Delete
extend Stripe::APIOperations::List
def self.url
def self.resource_url
"/v1/bitcoin/receivers"
end
def url
def resource_url
if respond_to?(:customer) && !self.customer.nil?
"#{Customer.url}/#{CGI.escape(customer)}/sources/#{CGI.escape(id)}"
"#{Customer.resource_url}/#{CGI.escape(customer)}/sources/#{CGI.escape(id)}"
else
"#{self.class.url}/#{CGI.escape(id)}"
"#{self.class.resource_url}/#{CGI.escape(id)}"
end
end
end

View File

@ -2,7 +2,7 @@ module Stripe
class BitcoinTransaction < APIResource
extend Stripe::APIOperations::List
def self.url
def self.resource_url
"/v1/bitcoin/transactions"
end
end

View File

@ -4,13 +4,13 @@ module Stripe
include Stripe::APIOperations::Delete
extend Stripe::APIOperations::List
def url
def resource_url
if respond_to?(:recipient)
"#{Recipient.url}/#{CGI.escape(recipient)}/cards/#{CGI.escape(id)}"
"#{Recipient.resource_url}/#{CGI.escape(recipient)}/cards/#{CGI.escape(id)}"
elsif respond_to?(:customer)
"#{Customer.url}/#{CGI.escape(customer)}/sources/#{CGI.escape(id)}"
"#{Customer.resource_url}/#{CGI.escape(customer)}/sources/#{CGI.escape(id)}"
elsif respond_to?(:account)
"#{Account.url}/#{CGI.escape(account)}/external_accounts/#{CGI.escape(id)}"
"#{Account.resource_url}/#{CGI.escape(account)}/external_accounts/#{CGI.escape(id)}"
end
end

View File

@ -45,7 +45,7 @@ module Stripe
params = {
:fraud_details => { :user_report => 'fraudulent' }
}
response, opts = request(:post, url, params)
response, opts = request(:post, resource_url, params)
initialize_from(response, opts)
end
@ -53,28 +53,28 @@ module Stripe
params = {
:fraud_details => { :user_report => 'safe' }
}
response, opts = request(:post, url, params)
response, opts = request(:post, resource_url, params)
initialize_from(response, opts)
end
private
def capture_url
url + '/capture'
resource_url + '/capture'
end
def dispute_url
url + '/dispute'
resource_url + '/dispute'
end
def close_dispute_url
url + '/dispute/close'
resource_url + '/dispute/close'
end
# Note that this is actually the *old* refund URL and its use is no longer
# preferred.
def refund_url
url + '/refund'
resource_url + '/refund'
end
end
end

View File

@ -2,7 +2,7 @@ module Stripe
class CountrySpec < APIResource
extend Stripe::APIOperations::List
def self.url
def self.resource_url
'/v1/country_specs'
end
end

View File

@ -61,15 +61,15 @@ module Stripe
private
def discount_url
url + '/discount'
resource_url + '/discount'
end
def subscription_url
url + '/subscription'
resource_url + '/subscription'
end
def subscriptions_url
url + '/subscriptions'
resource_url + '/subscriptions'
end
end
end

View File

@ -10,7 +10,7 @@ module Stripe
end
def close_url
url + '/close'
resource_url + '/close'
end
end
end

View File

@ -3,7 +3,7 @@ module Stripe
extend Stripe::APIOperations::Create
extend Stripe::APIOperations::List
def self.url
def self.resource_url
"/v1/files"
end

View File

@ -17,11 +17,11 @@ module Stripe
private
def self.upcoming_url
url + '/upcoming'
resource_url + '/upcoming'
end
def pay_url
url + '/pay'
resource_url + '/pay'
end
end
end

View File

@ -64,7 +64,7 @@ module Stripe
def retrieve(id, opts={})
id, retrieve_params = Util.normalize_id(id)
response, opts = request(:get,"#{url}/#{CGI.escape(id)}", retrieve_params, opts)
response, opts = request(:get,"#{resource_url}/#{CGI.escape(id)}", retrieve_params, opts)
Util.convert_to_stripe_object(response, opts)
end

View File

@ -12,7 +12,7 @@ module Stripe
private
def pay_url
url + "/pay"
resource_url + "/pay"
end
end

View File

@ -4,14 +4,5 @@ module Stripe
extend Stripe::APIOperations::Create
include Stripe::APIOperations::Update
include Stripe::APIOperations::Delete
# Keep APIResource#url as `api_url` to avoid letting the external URL
# replace the Stripe URL.
alias_method :api_url, :url
# Override Stripe::APIOperations::Update#save to explicitly pass URL.
def save
super(:req_url => api_url)
end
end
end

View File

@ -3,8 +3,8 @@ module Stripe
include Stripe::APIOperations::Update
extend Stripe::APIOperations::List
def url
"#{Transfer.url}/#{CGI.escape(transfer)}/reversals/#{CGI.escape(id)}"
def resource_url
"#{Transfer.resource_url}/#{CGI.escape(transfer)}/reversals/#{CGI.escape(id)}"
end
def self.retrieve(id, opts={})

View File

@ -1,14 +1,14 @@
module Stripe
class SingletonAPIResource < APIResource
def self.url
def self.resource_url
if self == SingletonAPIResource
raise NotImplementedError.new('SingletonAPIResource is an abstract class. You should perform actions on its subclasses (Account, etc.)')
end
"/v1/#{CGI.escape(class_name.downcase)}"
end
def url
self.class.url
def resource_url
self.class.resource_url
end
def self.retrieve(opts={})

View File

@ -3,8 +3,8 @@ module Stripe
include Stripe::APIOperations::Update
include Stripe::APIOperations::Delete
def url
"#{Customer.url}/#{CGI.escape(customer)}/subscriptions/#{CGI.escape(id)}"
def resource_url
"#{Customer.resource_url}/#{CGI.escape(customer)}/subscriptions/#{CGI.escape(id)}"
end
def self.retrieve(id, opts=nil)
@ -19,7 +19,7 @@ module Stripe
private
def discount_url
url + '/discount'
resource_url + '/discount'
end
end
end

View File

@ -10,7 +10,7 @@ module Stripe
end
def cancel_url
url + '/cancel'
resource_url + '/cancel'
end
end

View File

@ -121,7 +121,7 @@ module Stripe
:id => 'acct_1234',
:external_accounts => {
:object => "list",
:url => "/v1/accounts/acct_1234/external_accounts",
:resource_url => "/v1/accounts/acct_1234/external_accounts",
:data => [],
}
}
@ -140,7 +140,7 @@ module Stripe
:id => 'acct_1234',
:external_accounts => {
:object => "list",
:url => "/v1/accounts/acct_1234/external_accounts",
:resource_url => "/v1/accounts/acct_1234/external_accounts",
:data => [{
:id => "ba_1234",
:object => "bank_account",

View File

@ -671,7 +671,7 @@ module Stripe
err = assert_raises Stripe::APIConnectionError do
Stripe::Charge.create(:amount => 50, :currency => 'usd', :card => { :number => nil })
end
end
assert_match(/Request was retried 2 times/, err.message)
end

View File

@ -6,8 +6,8 @@ module Stripe
@mock.expects(:get).once.
returns(make_response(country_spec_array))
c = Stripe::CountrySpec.list
assert_equal('/v1/country_specs', c.url)
assert_equal('/v1/country_specs', c.resource_url)
assert_equal('list', c.object)
assert(c.data.kind_of?(Array))
assert_equal('US', c.data[0].id)
@ -20,17 +20,17 @@ module Stripe
with('https://api.stripe.com/v1/country_specs/US', nil, nil).
returns(make_response(resp))
s = Stripe::CountrySpec.retrieve('US')
assert_equal('/v1/country_specs/US', s.url)
assert_equal('/v1/country_specs/US', s.resource_url)
assert_equal('country_spec', s.object)
assert(s.kind_of?(Stripe::CountrySpec))
s.supported_bank_account_currencies.map{ |k,v| assert v.kind_of?(Array) }
assert_equal(['US'], s.supported_bank_account_currencies['usd'])
assert(s.supported_payment_currencies.include?('usd'))
assert s.supported_payment_currencies.kind_of?(Array)
assert s.supported_payment_methods.kind_of?(Array)
['individual', 'company'].map{ |type|
item = s.verification_fields[type]
assert item.minimum.include?('external_account')
@ -40,4 +40,4 @@ module Stripe
}
end
end
end
end

View File

@ -17,14 +17,14 @@ module Stripe
assert cards[0].kind_of? Stripe::Card
end
should "customer cards should have the correct url" do
should "customer cards should have the correct resource url" do
c = customer
@mock.expects(:get).once.returns(make_response(make_card(
:id => 'test_card',
:customer => 'test_customer'
)))
card = c.sources.retrieve('card')
assert_equal CUSTOMER_CARD_URL, card.url
assert_equal CUSTOMER_CARD_URL, card.resource_url
end
should "customer cards should be deletable" do

View File

@ -139,10 +139,10 @@ module Stripe
@mock.expects(:get).twice.returns(make_response(make_charge_array))
c = Stripe::Charge.all
assert c.kind_of?(Stripe::ListObject)
assert_equal('/v1/charges', c.url)
assert_equal('/v1/charges', c.resource_url)
all = c.all
assert all.kind_of?(Stripe::ListObject)
assert_equal('/v1/charges', all.url)
assert_equal('/v1/charges', all.resource_url)
assert all.data.kind_of?(Array)
end
end
@ -150,7 +150,7 @@ end
# A helper class with a URL that allows us to try out pagination.
class TestListObject < Stripe::ListObject
def url
def resource_url
"/things"
end
end

View File

@ -17,14 +17,14 @@ module Stripe
assert cards[0].kind_of? Stripe::Card
end
should "recipient cards should have the correct url" do
should "recipient cards should have the correct resource url" do
c = recipient
@mock.expects(:get).once.returns(make_response(make_card(
:id => 'test_card',
:recipient => 'test_recipient'
)))
card = c.cards.retrieve('card')
assert_equal RECIPIENT_CARD_URL, card.url
assert_equal RECIPIENT_CARD_URL, card.resource_url
end
should "recipient cards should be deletable" do

View File

@ -56,7 +56,7 @@ module Stripe
{
:data => [make_balance_transaction, make_balance_transaction, make_balance_transaction],
:object => "list",
:url => "/v1/balance/history"
:resource_url => "/v1/balance/history"
}
end
@ -93,7 +93,7 @@ module Stripe
{
:data => [make_application_fee, make_application_fee, make_application_fee],
:object => 'list',
:url => '/v1/application_fees'
:resource_url => '/v1/application_fees'
}
end
@ -101,7 +101,7 @@ module Stripe
{
:data => [make_application_fee_refund, make_application_fee_refund, make_application_fee_refund],
:object => 'list',
:url => '/v1/application_fees/' + fee_id + '/refunds'
:resource_url => '/v1/application_fees/' + fee_id + '/refunds'
}
end
@ -126,7 +126,7 @@ module Stripe
{
:data => [make_customer, make_customer, make_customer],
:object => 'list',
:url => '/v1/customers'
:resource_url => '/v1/customers'
}
end
@ -160,7 +160,7 @@ module Stripe
{
:data => [make_charge, make_charge, make_charge],
:object => 'list',
:url => '/v1/charges'
:resource_url => '/v1/charges'
}
end
@ -184,7 +184,7 @@ module Stripe
{
:data => [make_dispute, make_dispute, make_dispute],
:object => 'list',
:url => '/v1/disputes'
:resource_url => '/v1/disputes'
}
end
@ -192,7 +192,7 @@ module Stripe
{
:data => [make_card, make_card, make_card],
:object => 'list',
:url => '/v1/recipients/' + recipient_id + '/cards'
:resource_url => '/v1/recipients/' + recipient_id + '/cards'
}
end
@ -200,7 +200,7 @@ module Stripe
{
:data => [make_card, make_card, make_card],
:object => 'list',
:url => '/v1/customers/' + customer_id + '/sources'
:resource_url => '/v1/customers/' + customer_id + '/sources'
}
end
@ -235,7 +235,7 @@ module Stripe
:created => 1403047735,
:size => 4908,
:purpose => params[:purpose] || "dispute_evidence",
:url => nil,
:resource_url => nil,
:type => nil,
}
end
@ -244,7 +244,7 @@ module Stripe
{
:data => [make_file, make_file, make_file],
:object => 'list',
:url => '/v1/files'
:resource_url => '/v1/files'
}
end
@ -287,7 +287,7 @@ module Stripe
{
:data => [make_subscription, make_subscription, make_subscription],
:object => 'list',
:url => '/v1/customers/' + customer_id + '/subscriptions'
:resource_url => '/v1/customers/' + customer_id + '/subscriptions'
}
end
@ -297,7 +297,7 @@ module Stripe
{
:data => [make_refund(p), make_refund(p), make_refund(p)],
:object => 'list',
:url => charge ? "/v1/charges/#{charge}/refunds" : '/v1/refunds'
:resource_url => charge ? "/v1/charges/#{charge}/refunds" : '/v1/refunds'
}
end
@ -305,7 +305,7 @@ module Stripe
{
:data => [make_reversal, make_reversal, make_reversal],
:object => 'list',
:url => '/v1/transfers/' + transfer_id + '/reversals'
:resource_url => '/v1/transfers/' + transfer_id + '/reversals'
}
end
@ -366,7 +366,7 @@ module Stripe
{
:data => [make_invoice],
:object => 'list',
:url => '/v1/invoices?customer=test_customer'
:resource_url => '/v1/invoices?customer=test_customer'
}
end
@ -396,7 +396,7 @@ module Stripe
{
:data => [make_recipient, make_recipient, make_recipient],
:object => 'list',
:url => '/v1/recipients'
:resource_url => '/v1/recipients'
}
end
@ -427,7 +427,7 @@ module Stripe
{
:data => [make_transfer, make_transfer, make_transfer],
:object => 'list',
:url => '/v1/transfers'
:resource_url => '/v1/transfers'
}
end
@ -466,7 +466,7 @@ module Stripe
{
:data => [make_bitcoin_receiver, make_bitcoin_receiver, make_bitcoin_receiver],
:object => 'list',
:url => '/v1/bitcoin/receivers'
:resource_url => '/v1/bitcoin/receivers'
}
end
@ -485,7 +485,7 @@ module Stripe
{
:data => [make_bitcoin_transaction, make_bitcoin_transaction, make_bitcoin_transaction],
:object => 'list',
:url => "/v1/bitcoin/receivers/btcrcv_test_receiver/transactions"
:resource_url => "/v1/bitcoin/receivers/btcrcv_test_receiver/transactions"
}
end
@ -567,7 +567,7 @@ module Stripe
def make_product_array
{
:object => "list",
:url => "/v1/products",
:resource_url => "/v1/products",
:data => [
make_product,
make_product,
@ -602,7 +602,7 @@ module Stripe
def make_sku_array(product_id, params={})
{
:object => "list",
:url => "/v1/skus",
:resource_url => "/v1/skus",
:data => [
make_sku(:product => product_id),
make_sku(:product => product_id),
@ -656,7 +656,7 @@ module Stripe
def make_order_array(params={})
{
:object => "list",
:url => "/v1/orders",
:resource_url => "/v1/orders",
:data => [
make_order,
make_order,
@ -675,7 +675,7 @@ module Stripe
def country_spec_array
{
:object => "list",
:url => "/v1/country_specs",
:resource_url => "/v1/country_specs",
:data => [
make_country_spec,
make_country_spec,
@ -709,7 +709,7 @@ module Stripe
"tos_acceptance.ip"
],
:additional => [
"legal_entity.personal_id_number",
"legal_entity.personal_id_number",
"legal_entity.verification.document"
]
},