Last active
August 29, 2015 14:01
-
-
Save nateklaiber/53c918b468ed1921a33b to your computer and use it in GitHub Desktop.
Revisions
-
nateklaiber revised this gist
May 28, 2014 . 1 changed file with 9 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -51,6 +51,15 @@ charge.customer With that last part, for the sake of consistency, I want to always return a `Stripe::Model::Customer` object. This means the `customer` method needs to know if it's expanded or not. If not, then it doesn't need to make an extra request. If only the ID is provided, it needs to lazy load the `Customer` via another API call. This way, a consumer of the client can safely call: ```ruby charge.customer.email charge.customer.account_balance ``` They don't have to determine, from the outer scope, if they need to make a second request based on the value of `customer`. This is why I'd prefer a method of `customer_id` and `customer` as different envelopes. Stripe could have returned the nested object: ```json -
nateklaiber revised this gist
May 28, 2014 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -22,7 +22,7 @@ connection = Stripe::Connection.new(configuration) # Make a request to the API. This is normally wrapped in a specific `Request` model. request_handler = Stripe::RequestHandler.new(connection) request = request.get(charge_detail_url) # Retrieve the response body as JSON response = request.body -
nateklaiber revised this gist
May 28, 2014 . 1 changed file with 3 additions and 2 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -13,8 +13,9 @@ I'll use Stripe as an example. The client is responsible for: configuration = Stripe::Configuration.new(config_params_or_block) # Find the route I want to make the request against routes = Stripe::Client.routes charge_detail_route = routes.route_for('charge-detail') charge_detail_url = charge_detail.url_for(id: 'ch_1047M22eZvKYlo2CzsVZ0cX8') # Make a connection to the API connection = Stripe::Connection.new(configuration) -
nateklaiber created this gist
May 28, 2014 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,67 @@ I'll use Stripe as an example. The client is responsible for: * Configuration * Routing * Connection Handling * Request Handling * Raw requests with JSON * Object model requests that wrap the raw request (allow us to say `Stripe::Request::Charge.get(id: 'sdfsdf')`) * Object Creation. This includes top level and associations. ```ruby # Configuration and setup configuration = Stripe::Configuration.new(config_params_or_block) # Find the route I want to make the request against router = Stripe::Client.routes.route_for('charge-detail') endpoint = router.url_for(id: 'ch_1047M22eZvKYlo2CzsVZ0cX8') # Make a connection to the API connection = Stripe::Connection.new(configuration) # Make a request to the API. This is normally wrapped in a specific `Request` model. request_handler = Stripe::RequestHandler.new(connection) request = request.get(endpoint) # Retrieve the response body as JSON response = request.body # Wrap in an object model charge = Stripe::Model::Charge.new(response) # Now we can interact with the model and it's attributes... charge.created # => 1401284558 charge.paid # => true # Now, the `customer` is expandable. If it exists, then it's an `ID` by default. If expanded, then it's the full representation. # Without expansion. charge.customer # => 'cus_47Ltj7MTZguSEN' # With expansion. We wrap it in the `Customer` model. charge.customer # => Stripe::Model::Customer ``` With that last part, for the sake of consistency, I want to always return a `Stripe::Model::Customer` object. This means the `customer` method needs to know if it's expanded or not. If not, then it doesn't need to make an extra request. If only the ID is provided, it needs to lazy load the `Customer` via another API call. This is why I'd prefer a method of `customer_id` and `customer` as different envelopes. Stripe could have returned the nested object: ```json { "customer": { "id": "cus_47Ltj7MTZguSEN" } } ``` However, I am still left to inspect the object to determine if we have the _full_ object or only the `ID`. I am also open to there being better approaches. When I build API clients, I like to keep a clean separation of responsibilities without intermixing different aspects. Any feedback would be welcome.