Create if #save is called on a new object

Modifies the behavior of an update so that it can create an object if it
was new. This allows an "upsert"-like functionality where the SDK will
tend to do the right/expected thing.

This is a tad janky in that it checks for the existence of a class-level
`.create` method which is expected to come from a different module, but
most modules in the project are already fairly deeply intertwined and
co-dependent.

Fixes #165.
This commit is contained in:
Brandur 2015-09-29 17:36:01 -07:00
parent fef7f8c641
commit ac7d050ecf
2 changed files with 31 additions and 1 deletions

View File

@ -3,10 +3,12 @@ module Stripe
module Update
def save(params={})
# Let the caller override the URL but avoid serializing it.
req_url = params.delete(:req_url) || url
req_url = params.delete(:req_url) || save_url
values = self.class.serialize_params(self).merge(params)
if values.length > 0
# note that id gets removed here our call to #url above has already
# generated a uri for this object with an identifier baked in
values.delete(:id)
response, opts = request(:post, req_url, values)
@ -14,6 +16,22 @@ module Stripe
end
self
end
private
def save_url
# This switch essentially allows us "upsert"-like functionality. If the
# API resource doesn't have an ID set (suggesting that it's new) and
# its class responds to .create (which comes from
# Stripe::APIOperations::Create), then use the URL to create a new
# 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
else
url
end
end
end
end
end

View File

@ -627,6 +627,18 @@ module Stripe
acct.save
end
should 'should create a new resource when an object without an id is saved' do
account = Stripe::Account.construct_from({
:id => nil,
:display_name => nil,
})
@mock.expects(:post).once.with("#{Stripe.api_base}/v1/accounts", nil, 'display_name=stripe').returns(make_response({"id" => "charge_id"}))
account.display_name = 'stripe'
account.save
end
end
end
end