Class: ChartMogul::APIResource
- Extended by:
- Forwardable
- Defined in:
- lib/chartmogul/api_resource.rb
Direct Known Subclasses
Account, Contact, Contacts, Customer, CustomerInvoices, Customers, DataSource, DataSources, Enrichment::Customers, Enrichment::DeprecatedCustomer, Invoice, Invoices, JsonImport, LineItem, Metrics::ARPAs, Metrics::ARRs, Metrics::ASPs, Metrics::Activities, Metrics::ActivitiesExport, Metrics::AllKeyMetrics, Metrics::CustomerChurnRates, Metrics::CustomerCounts, Metrics::Customers::Activities, Metrics::Customers::Subscriptions, Metrics::LTVs, Metrics::MRRChurnRates, Metrics::MRRs, Note, Notes, Opportnities, Opportunity, Ping, Plan, PlanGroup, PlanGroup::PlanGroups, PlanGroups::Plans, Plans, Subscription, SubscriptionEvent, SubscriptionEvents, Subscriptions, Task, Tasks, Transaction, Transactions::Payment, Transactions::Refund
Constant Summary collapse
- RETRY_STATUSES =
[429, *500..599].freeze
- RETRY_EXCEPTIONS =
[ "Faraday::ConnectionFailed", "Faraday::RetriableResponse" ].freeze
- BACKOFF_FACTOR =
2- INTERVAL_RANDOMNESS =
0.5- INTERVAL =
1- MAX_INTERVAL =
60- THREAD_CONNECTION_KEY =
"chartmogul_ruby.api_resource.connection"
Class Attribute Summary collapse
-
.resource_name ⇒ Object
readonly
Returns the value of attribute resource_name.
-
.resource_path ⇒ Object
readonly
Returns the value of attribute resource_path.
-
.resource_root_key ⇒ Object
readonly
Returns the value of attribute resource_root_key.
Class Method Summary collapse
- .build_connection ⇒ Object
-
.build_query_path(base_path, **params) ⇒ Object
Build a URL path with query parameters, handling ? vs & correctly.
- .connection ⇒ Object
-
.custom_with_query_params!(http_method, body_data = {}, resource_key = nil) ⇒ Object
Class method version for enhanced custom! with query parameters.
- .extract_query_params(attrs, resource_key = nil) ⇒ Object
- .handle_other_error(exception) ⇒ Object
- .handle_request_error(exception) ⇒ Object
- .handling_errors ⇒ Object
- .immutable_keys ⇒ Object
-
.json_patch(path, body) ⇒ Object
Convenience for JSON PATCH requests.
-
.json_post(path, body) ⇒ Object
Convenience for JSON POST requests.
-
.json_put(path, body) ⇒ Object
Convenience for JSON PUT requests.
- .query_params ⇒ Object
-
.set_immutable_keys(array) ⇒ Object
When set with keys, nested hash keys of these immutable keys won’t be converted to snake case.
- .set_resource_name(name) ⇒ Object
- .set_resource_path(path) ⇒ Object
- .set_resource_root_key(root_key) ⇒ Object
- .writeable_query_param(attribute, options = {}) ⇒ Object
Instance Method Summary collapse
-
#custom_with_query_params!(http_method, body_data = {}, resource_key = nil) ⇒ Object
Enhanced custom! that automatically handles query parameters.
- #extract_query_params(attrs, resource_key = nil) ⇒ Object
-
#path_with_query_params(attrs) ⇒ Object
Generate path with query parameters applied.
Methods inherited from Object
#allowed_for_write?, #assign_all_attributes, #assign_writeable_attributes, attributes, define_private_writer, define_reader, define_writer, #initialize, #instance_attributes, new_from_json, readonly_attr, #serialize_for_write, #serialized_value_for_attr, writeable_attr, writeable_attributes
Constructor Details
This class inherits a constructor from ChartMogul::Object
Class Attribute Details
.resource_name ⇒ Object (readonly)
Returns the value of attribute resource_name.
23 24 25 |
# File 'lib/chartmogul/api_resource.rb', line 23 def resource_name @resource_name end |
.resource_path ⇒ Object (readonly)
Returns the value of attribute resource_path.
23 24 25 |
# File 'lib/chartmogul/api_resource.rb', line 23 def resource_path @resource_path end |
.resource_root_key ⇒ Object (readonly)
Returns the value of attribute resource_root_key.
23 24 25 |
# File 'lib/chartmogul/api_resource.rb', line 23 def resource_root_key @resource_root_key end |
Class Method Details
.build_connection ⇒ Object
200 201 202 203 204 205 206 207 208 209 210 |
# File 'lib/chartmogul/api_resource.rb', line 200 def self.build_connection Faraday.new(url: ChartMogul.api_base, headers: { "User-Agent" => "chartmogul-ruby/#{ChartMogul::VERSION}" }) do |faraday| faraday.use Faraday::Response::RaiseError faraday.request :authorization, :basic, ChartMogul.api_key, "" faraday.request :retry, max: ChartMogul.max_retries, retry_statuses: RETRY_STATUSES, max_interval: MAX_INTERVAL, backoff_factor: BACKOFF_FACTOR, interval_randomness: INTERVAL_RANDOMNESS, interval: INTERVAL, exceptions: RETRY_EXCEPTIONS faraday.adapter Faraday::Adapter::NetHttp end end |
.build_query_path(base_path, **params) ⇒ Object
Build a URL path with query parameters, handling ? vs & correctly
168 169 170 171 172 173 174 |
# File 'lib/chartmogul/api_resource.rb', line 168 def self.build_query_path(base_path, **params) filtered = params.compact return base_path if filtered.empty? separator = base_path.include?("?") ? "&" : "?" "#{base_path}#{separator}#{URI.encode_www_form(filtered)}" end |
.connection ⇒ Object
74 75 76 |
# File 'lib/chartmogul/api_resource.rb', line 74 def self.connection Thread.current[THREAD_CONNECTION_KEY] ||= build_connection end |
.custom_with_query_params!(http_method, body_data = {}, resource_key = nil) ⇒ Object
Class method version for enhanced custom! with query parameters
157 158 159 160 161 162 163 164 165 |
# File 'lib/chartmogul/api_resource.rb', line 157 def self.custom_with_query_params!(http_method, body_data = {}, resource_key = nil) attrs, query_params = extract_query_params(body_data, resource_key) # Only include path parameters from body data, plus extracted query parameters path_params = body_data.select { |key, _| resource_path.named_params.values.include?(key) } path_and_query_params = path_params.merge(query_params) path = resource_path.apply_with_get_params(path_and_query_params) custom!(http_method, path, attrs) end |
.extract_query_params(attrs, resource_key = nil) ⇒ Object
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
# File 'lib/chartmogul/api_resource.rb', line 34 def self.extract_query_params(attrs, resource_key = nil) remaining_attrs = attrs.dup query_params = {} self.query_params.each do |param| # If resource_key is specified, look in nested structure if resource_key && remaining_attrs[resource_key].is_a?(Hash) && remaining_attrs[resource_key]&.key?(param) && remaining_attrs[resource_key][param] query_params[param] = remaining_attrs[resource_key].delete(param) # Otherwise look at top level elsif remaining_attrs.key?(param) && remaining_attrs[param] query_params[param] = remaining_attrs.delete(param) end end [remaining_attrs, query_params] end |
.handle_other_error(exception) ⇒ Object
114 115 116 |
# File 'lib/chartmogul/api_resource.rb', line 114 def self.handle_other_error(exception) raise ChartMogul::ChartMogulError, exception. end |
.handle_request_error(exception) ⇒ Object
86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 |
# File 'lib/chartmogul/api_resource.rb', line 86 def self.handle_request_error(exception) response = exception.response[:body] http_status = exception.response[:status] case http_status when 400 = "JSON schema validation hasn't passed." raise ChartMogul::SchemaInvalidError.new(, http_status: 400, response: response) when 401 = "No valid API key provided" raise ChartMogul::UnauthorizedError.new(, http_status: 401, response: response) when 403 = "The requested action is forbidden." raise ChartMogul::ForbiddenError.new(, http_status: 403, response: response) when 404 = "The requested #{resource_name} could not be found." raise ChartMogul::NotFoundError.new(, http_status: 404, response: response) when 422 = "The #{resource_name} could not be created or updated." raise ChartMogul::ResourceInvalidError.new(, http_status: 422, response: response) when 500..504 = "ChartMogul API server response error" raise ChartMogul::ServerError.new(, http_status: http_status, response: response) else = "#{resource_name} request error has occurred." raise ChartMogul::ChartMogulError.new(, http_status: http_status, response: response) end end |
.handling_errors ⇒ Object
78 79 80 81 82 83 84 |
# File 'lib/chartmogul/api_resource.rb', line 78 def self.handling_errors yield rescue Faraday::ClientError, Faraday::ServerError => e e.response ? handle_request_error(e) : handle_other_error(e) rescue StandardError => e handle_other_error(e) end |
.immutable_keys ⇒ Object
65 66 67 |
# File 'lib/chartmogul/api_resource.rb', line 65 def self.immutable_keys @immutable_keys ||= [] end |
.json_patch(path, body) ⇒ Object
Convenience for JSON PATCH requests
177 178 179 180 181 182 |
# File 'lib/chartmogul/api_resource.rb', line 177 def self.json_patch(path, body) connection.patch(path) do |req| req.headers["Content-Type"] = "application/json" req.body = JSON.dump(body) end end |
.json_post(path, body) ⇒ Object
Convenience for JSON POST requests
193 194 195 196 197 198 |
# File 'lib/chartmogul/api_resource.rb', line 193 def self.json_post(path, body) connection.post(path) do |req| req.headers["Content-Type"] = "application/json" req.body = JSON.dump(body) end end |
.json_put(path, body) ⇒ Object
Convenience for JSON PUT requests
185 186 187 188 189 190 |
# File 'lib/chartmogul/api_resource.rb', line 185 def self.json_put(path, body) connection.put(path) do |req| req.headers["Content-Type"] = "application/json" req.body = JSON.dump(body) end end |
.query_params ⇒ Object
25 26 27 |
# File 'lib/chartmogul/api_resource.rb', line 25 def self.query_params @query_params ||= Set.new end |
.set_immutable_keys(array) ⇒ Object
When set with keys, nested hash keys of these immutable keys won’t be converted to snake case
70 71 72 |
# File 'lib/chartmogul/api_resource.rb', line 70 def self.set_immutable_keys(array) @immutable_keys = array end |
.set_resource_name(name) ⇒ Object
57 58 59 |
# File 'lib/chartmogul/api_resource.rb', line 57 def self.set_resource_name(name) @resource_name = name end |
.set_resource_path(path) ⇒ Object
53 54 55 |
# File 'lib/chartmogul/api_resource.rb', line 53 def self.set_resource_path(path) @resource_path = ChartMogul::ResourcePath.new(path) end |
.set_resource_root_key(root_key) ⇒ Object
61 62 63 |
# File 'lib/chartmogul/api_resource.rb', line 61 def self.set_resource_root_key(root_key) @resource_root_key = root_key end |
.writeable_query_param(attribute, options = {}) ⇒ Object
29 30 31 32 |
# File 'lib/chartmogul/api_resource.rb', line 29 def self.writeable_query_param(attribute, = {}) query_params << attribute.to_sym writeable_attr(attribute, ) end |
Instance Method Details
#custom_with_query_params!(http_method, body_data = {}, resource_key = nil) ⇒ Object
Enhanced custom! that automatically handles query parameters
146 147 148 149 150 151 152 153 154 |
# File 'lib/chartmogul/api_resource.rb', line 146 def custom_with_query_params!(http_method, body_data = {}, resource_key = nil) attrs, query_params = extract_query_params(body_data, resource_key) # Only include path parameters from instance attributes, plus extracted query parameters path_params = instance_attributes.select { |key, _| resource_path.named_params.values.include?(key) } path_and_query_params = path_params.merge(query_params) path = resource_path.apply_with_get_params(path_and_query_params) custom!(http_method, path, attrs) end |
#extract_query_params(attrs, resource_key = nil) ⇒ Object
120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 |
# File 'lib/chartmogul/api_resource.rb', line 120 def extract_query_params(attrs, resource_key = nil) remaining_attrs = attrs.dup query_params = {} self.class.query_params.each do |param| # If resource_key is specified, look in nested structure if resource_key && remaining_attrs[resource_key].is_a?(Hash) && remaining_attrs[resource_key]&.key?(param) && remaining_attrs[resource_key][param] query_params[param] = remaining_attrs[resource_key].delete(param) # Otherwise look at top level elsif remaining_attrs.key?(param) && remaining_attrs[param] query_params[param] = remaining_attrs.delete(param) end end [remaining_attrs, query_params] end |
#path_with_query_params(attrs) ⇒ Object
Generate path with query parameters applied
140 141 142 143 |
# File 'lib/chartmogul/api_resource.rb', line 140 def path_with_query_params(attrs) _, query_params = extract_query_params(attrs) query_params.empty? ? resource_path.path : resource_path.apply_with_get_params(query_params) end |