chartmogul-ruby 1.5.1 → 1.6.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (70) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.travis.yml +5 -1
  4. data/Gemfile +2 -0
  5. data/LICENSE.txt +1 -1
  6. data/README.md +5 -3
  7. data/Rakefile +2 -0
  8. data/bin/console +1 -0
  9. data/chartmogul-ruby.gemspec +21 -17
  10. data/fixtures/vcr_cassettes/ChartMogul_APIResource/connection/works_in_a_threaded_environment.yml +112 -0
  11. data/fixtures/vcr_cassettes/ChartMogul_APIResource/connection/works_when_credentials_are_updated.yml +77 -0
  12. data/fixtures/vcr_cassettes/ChartMogul_Customer/API_Interactions/updates_customer_using_class_method.yml +53 -0
  13. data/fixtures/vcr_cassettes/ChartMogul_CustomerInvoices/API_Interactions/correctly_interracts_with_the_API.yml +148 -109
  14. data/fixtures/vcr_cassettes/ChartMogul_Plan/API_Interactions/updates_existing_plan_using_class_method.yml +164 -0
  15. data/fixtures/vcr_cassettes/ChartMogul_PlanGroup/API_interactions/updates_existing_plan_group_name_via_class_method.yml +297 -0
  16. data/lib/chartmogul.rb +8 -2
  17. data/lib/chartmogul/api/actions/all.rb +2 -0
  18. data/lib/chartmogul/api/actions/create.rb +2 -0
  19. data/lib/chartmogul/api/actions/custom.rb +2 -0
  20. data/lib/chartmogul/api/actions/destroy.rb +2 -0
  21. data/lib/chartmogul/api/actions/retrieve.rb +2 -0
  22. data/lib/chartmogul/api/actions/update.rb +22 -0
  23. data/lib/chartmogul/api_resource.rb +21 -12
  24. data/lib/chartmogul/concerns/entries.rb +2 -0
  25. data/lib/chartmogul/concerns/pageable.rb +2 -0
  26. data/lib/chartmogul/concerns/pageable2.rb +2 -0
  27. data/lib/chartmogul/concerns/summary.rb +2 -0
  28. data/lib/chartmogul/config_attributes.rb +7 -1
  29. data/lib/chartmogul/configuration.rb +3 -0
  30. data/lib/chartmogul/customer.rb +2 -0
  31. data/lib/chartmogul/customer_invoices.rb +11 -0
  32. data/lib/chartmogul/data_source.rb +2 -0
  33. data/lib/chartmogul/enrichment/customer.rb +2 -0
  34. data/lib/chartmogul/errors/chartmogul_error.rb +2 -0
  35. data/lib/chartmogul/errors/configuration_error.rb +2 -0
  36. data/lib/chartmogul/errors/forbidden_error.rb +2 -0
  37. data/lib/chartmogul/errors/not_found_error.rb +2 -0
  38. data/lib/chartmogul/errors/resource_invalid_error.rb +2 -0
  39. data/lib/chartmogul/errors/schema_invalid_error.rb +2 -0
  40. data/lib/chartmogul/errors/server_error.rb +2 -0
  41. data/lib/chartmogul/errors/unauthorized_error.rb +2 -0
  42. data/lib/chartmogul/invoice.rb +2 -0
  43. data/lib/chartmogul/line_items/one_time.rb +2 -0
  44. data/lib/chartmogul/line_items/subscription.rb +2 -0
  45. data/lib/chartmogul/metrics/activity.rb +2 -0
  46. data/lib/chartmogul/metrics/all_key_metrics.rb +2 -0
  47. data/lib/chartmogul/metrics/arpa.rb +2 -0
  48. data/lib/chartmogul/metrics/arr.rb +2 -0
  49. data/lib/chartmogul/metrics/asp.rb +2 -0
  50. data/lib/chartmogul/metrics/base.rb +6 -2
  51. data/lib/chartmogul/metrics/customer_churn_rate.rb +2 -0
  52. data/lib/chartmogul/metrics/customer_count.rb +2 -0
  53. data/lib/chartmogul/metrics/ltv.rb +2 -0
  54. data/lib/chartmogul/metrics/mrr.rb +2 -0
  55. data/lib/chartmogul/metrics/mrr_churn_rate.rb +2 -0
  56. data/lib/chartmogul/metrics/subscription.rb +2 -0
  57. data/lib/chartmogul/object.rb +2 -0
  58. data/lib/chartmogul/ping.rb +2 -0
  59. data/lib/chartmogul/plan.rb +2 -0
  60. data/lib/chartmogul/plan_group.rb +2 -0
  61. data/lib/chartmogul/plan_groups/plans.rb +2 -0
  62. data/lib/chartmogul/resource_path.rb +6 -1
  63. data/lib/chartmogul/subscription.rb +2 -0
  64. data/lib/chartmogul/summary.rb +2 -0
  65. data/lib/chartmogul/transactions/payment.rb +2 -0
  66. data/lib/chartmogul/transactions/refund.rb +2 -0
  67. data/lib/chartmogul/utils/hash_snake_caser.rb +2 -0
  68. data/lib/chartmogul/utils/json_parser.rb +11 -1
  69. data/lib/chartmogul/version.rb +3 -1
  70. metadata +64 -17
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'time'
2
4
  require 'json'
3
5
  require 'faraday'
@@ -69,18 +71,22 @@ require 'chartmogul/metrics/subscription'
69
71
  require 'chartmogul/enrichment/customer'
70
72
 
71
73
  module ChartMogul
72
- API_BASE = 'https://api.chartmogul.com'.freeze
74
+ API_BASE = 'https://api.chartmogul.com'
73
75
  MAX_RETRIES = 20
76
+ CONFIG_THREAD_KEY = 'chartmogul_ruby.config'
74
77
 
75
78
  class << self
76
79
  extend ConfigAttributes
77
80
 
81
+
78
82
  def config
79
- @config ||= ChartMogul::Configuration.new
83
+ Thread.current[CONFIG_THREAD_KEY] = ChartMogul::Configuration.new if Thread.current[CONFIG_THREAD_KEY].nil?
84
+ Thread.current[CONFIG_THREAD_KEY]
80
85
  end
81
86
 
82
87
  config_accessor :account_token
83
88
  config_accessor :secret_key
84
89
  config_accessor :max_retries, MAX_RETRIES
90
+ config_accessor :api_base, API_BASE
85
91
  end
86
92
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ChartMogul
2
4
  module API
3
5
  module Actions
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ChartMogul
2
4
  module API
3
5
  module Actions
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ChartMogul
2
4
  module API
3
5
  module Actions
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ChartMogul
2
4
  module API
3
5
  module Actions
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ChartMogul
2
4
  module API
3
5
  module Actions
@@ -1,7 +1,13 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ChartMogul
2
4
  module API
3
5
  module Actions
4
6
  module Update
7
+ def self.included(base)
8
+ base.extend ClassMethods
9
+ end
10
+
5
11
  def update!
6
12
  resp = handling_errors do
7
13
  connection.patch("#{resource_path.apply(instance_attributes)}/#{uuid}") do |req|
@@ -13,6 +19,22 @@ module ChartMogul
13
19
 
14
20
  assign_all_attributes(json)
15
21
  end
22
+
23
+ module ClassMethods
24
+ def update!(uuid, attributes = {})
25
+ resource = new(attributes)
26
+
27
+ resp = handling_errors do
28
+ connection.patch("#{resource_path.apply(attributes)}/#{uuid}") do |req|
29
+ req.headers['Content-Type'] = 'application/json'
30
+ req.body = JSON.dump(resource.serialize_for_write)
31
+ end
32
+ end
33
+ json = ChartMogul::Utils::JSONParser.parse(resp.body)
34
+
35
+ new_from_json(json)
36
+ end
37
+ end
16
38
  end
17
39
  end
18
40
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'forwardable'
2
4
 
3
5
  module ChartMogul
@@ -13,6 +15,7 @@ module ChartMogul
13
15
  INTERVAL_RANDOMNESS = 0.5
14
16
  INTERVAL = 1
15
17
  MAX_INTERVAL = 60
18
+ THREAD_CONNECTION_KEY = 'chartmogul_ruby.api_resource.connection'
16
19
 
17
20
  class << self; attr_reader :resource_path, :resource_name, :resource_root_key end
18
21
 
@@ -29,22 +32,15 @@ module ChartMogul
29
32
  end
30
33
 
31
34
  def self.connection
32
- @connection ||= Faraday.new(url: ChartMogul::API_BASE) do |faraday|
33
- faraday.use Faraday::Request::BasicAuthentication, ChartMogul.account_token, ChartMogul.secret_key
34
- faraday.use Faraday::Response::RaiseError
35
- faraday.request :retry, max: ChartMogul.max_retries, retry_statuses: RETRY_STATUSES,
36
- max_interval: MAX_INTERVAL, backoff_factor: BACKOFF_FACTOR,
37
- interval_randomness: INTERVAL_RANDOMNESS, interval: INTERVAL, exceptions: RETRY_EXCEPTIONS
38
- faraday.use Faraday::Adapter::NetHttp
39
- end
35
+ Thread.current[THREAD_CONNECTION_KEY] ||= build_connection
40
36
  end
41
37
 
42
38
  def self.handling_errors
43
39
  yield
44
- rescue Faraday::ClientError => exception
45
- exception.response ? handle_request_error(exception) : handle_other_error(exception)
46
- rescue => exception
47
- handle_other_error(exception)
40
+ rescue Faraday::ClientError, Faraday::ServerError => e
41
+ e.response ? handle_request_error(e) : handle_other_error(e)
42
+ rescue StandardError => e
43
+ handle_other_error(e)
48
44
  end
49
45
 
50
46
  def self.handle_request_error(exception)
@@ -80,5 +76,18 @@ module ChartMogul
80
76
  end
81
77
 
82
78
  def_delegators 'self.class', :resource_path, :resource_name, :resource_root_key, :connection, :handling_errors
79
+
80
+ private
81
+
82
+ def self.build_connection
83
+ Faraday.new(url: ChartMogul.api_base) do |faraday|
84
+ faraday.use Faraday::Request::BasicAuthentication, ChartMogul.account_token, ChartMogul.secret_key
85
+ faraday.use Faraday::Response::RaiseError
86
+ faraday.request :retry, max: ChartMogul.max_retries, retry_statuses: RETRY_STATUSES,
87
+ max_interval: MAX_INTERVAL, backoff_factor: BACKOFF_FACTOR,
88
+ interval_randomness: INTERVAL_RANDOMNESS, interval: INTERVAL, exceptions: RETRY_EXCEPTIONS
89
+ faraday.adapter Faraday::Adapter::NetHttp
90
+ end
91
+ end
83
92
  end
84
93
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ChartMogul
2
4
  module Concerns
3
5
  module Entries
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ChartMogul
2
4
  module Concerns
3
5
  module Pageable
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ChartMogul
2
4
  module Concerns
3
5
  module Pageable2
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ChartMogul
2
4
  module Concerns
3
5
  module Summary
@@ -1,14 +1,20 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ChartMogul
2
4
  module ConfigAttributes
3
5
  def config_accessor(attribute, default_value = nil)
4
6
  define_method(attribute) do
5
7
  attr = config.send(attribute) || default_value
6
- raise ConfigurationError, "Configuration for #{attribute} not set" if attr.nil?
8
+ if attr.nil?
9
+ raise ConfigurationError, "Configuration for #{attribute} not set"
10
+ end
11
+
7
12
  attr
8
13
  end
9
14
 
10
15
  define_method("#{attribute}=") do |val|
11
16
  config.send("#{attribute}=", val)
17
+ Thread.current[ChartMogul::APIResource::THREAD_CONNECTION_KEY] = nil
12
18
  end
13
19
  end
14
20
  end
@@ -1,7 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ChartMogul
2
4
  class Configuration
3
5
  attr_accessor :account_token
4
6
  attr_accessor :secret_key
5
7
  attr_accessor :max_retries
8
+ attr_accessor :api_base
6
9
  end
7
10
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ChartMogul
2
4
  class Customer < APIResource
3
5
  set_resource_name 'Customer'
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'forwardable'
2
4
 
3
5
  module ChartMogul
@@ -24,6 +26,15 @@ module ChartMogul
24
26
  super(options.merge(customer_uuid: customer_uuid))
25
27
  end
26
28
 
29
+ def self.destroy_all!(data_source_uuid, customer_uuid)
30
+ path = ChartMogul::ResourcePath.new('v1/data_sources/:data_source_uuid/customers/:customer_uuid/invoices')
31
+ handling_errors do
32
+ connection.delete(path.apply(data_source_uuid: data_source_uuid, customer_uuid: customer_uuid))
33
+ end
34
+ true
35
+ end
36
+
37
+
27
38
  def_delegators :invoices, :each, :[], :<<, :size, :length, :empty?, :first
28
39
 
29
40
  private
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ChartMogul
2
4
  class DataSource < APIResource
3
5
  set_resource_name 'Data Source'
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ChartMogul
2
4
  module Enrichment
3
5
  # <b>DEPRECATED:</b> Please use <tt>ChartMogul/Customer</tt> instead.
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ChartMogul
2
4
  class ChartMogulError < StandardError
3
5
  attr_reader :error_message, :response, :http_status
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ChartMogul
2
4
  class ConfigurationError < ChartMogulError
3
5
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ChartMogul
2
4
  class ForbiddenError < ChartMogulError
3
5
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ChartMogul
2
4
  class NotFoundError < ChartMogulError
3
5
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ChartMogul
2
4
  class ResourceInvalidError < ChartMogulError
3
5
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ChartMogul
2
4
  class SchemaInvalidError < ChartMogulError
3
5
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ChartMogul
2
4
  class ServerError < ChartMogulError
3
5
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ChartMogul
2
4
  class UnauthorizedError < ChartMogulError
3
5
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ChartMogul
2
4
  class Invoice < APIResource
3
5
  set_resource_name 'Invoice'
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ChartMogul
2
4
  module LineItems
3
5
  class OneTime < ChartMogul::Object
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ChartMogul
2
4
  module LineItems
3
5
  class Subscription < ChartMogul::Object
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ChartMogul
2
4
  module Metrics
3
5
  class Activity < ChartMogul::Object
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ChartMogul
2
4
  module Metrics
3
5
  class AllKeyMetric < ChartMogul::Object
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ChartMogul
2
4
  module Metrics
3
5
  class ARPA < ChartMogul::Object
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ChartMogul
2
4
  module Metrics
3
5
  class ARR < ChartMogul::Object
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ChartMogul
2
4
  module Metrics
3
5
  class ASP < ChartMogul::Object
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ChartMogul
2
4
  module Metrics
3
5
  def self.all(options = {})
@@ -40,11 +42,13 @@ module ChartMogul
40
42
 
41
43
  def self.preprocess_params(options)
42
44
  %i[start_date end_date].each do |param_name|
43
- options[param_name.to_s.tr('_', '-')] = options.delete(param_name) if options[param_name]
45
+ if options[param_name]
46
+ options[param_name.to_s.tr('_', '-')] = options.delete(param_name)
47
+ end
44
48
  end
45
49
 
46
50
  %i[geo plans].each do |param_name|
47
- if options[param_name] && options[param_name].is_a?(Array)
51
+ if options[param_name]&.is_a?(Array)
48
52
  options[param_name] = options[param_name].join(',')
49
53
  end
50
54
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ChartMogul
2
4
  module Metrics
3
5
  class CustomerChurnRate < ChartMogul::Object
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ChartMogul
2
4
  module Metrics
3
5
  class CustomerCount < ChartMogul::Object
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ChartMogul
2
4
  module Metrics
3
5
  class LTV < ChartMogul::Object
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ChartMogul
2
4
  module Metrics
3
5
  class MRR < ChartMogul::Object
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ChartMogul
2
4
  module Metrics
3
5
  class MRRChurnRate < ChartMogul::Object
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ChartMogul
2
4
  module Metrics
3
5
  class Subscription < ChartMogul::Object
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'set'
2
4
 
3
5
  module ChartMogul