asana 0.10.3 → 2.0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (86) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/build.yml +24 -0
  3. data/.github/workflows/pubilsh-to-rubygem.yml +18 -0
  4. data/.github/workflows/publish-to-github-releases.yml +16 -0
  5. data/.gitignore +0 -1
  6. data/.rubocop.yml +38 -3
  7. data/.ruby-version +1 -1
  8. data/Appraisals +8 -3
  9. data/Gemfile +7 -3
  10. data/Gemfile.lock +166 -0
  11. data/Guardfile +12 -10
  12. data/README.md +45 -20
  13. data/Rakefile +20 -27
  14. data/VERSION +1 -1
  15. data/asana.gemspec +20 -18
  16. data/examples/Gemfile.lock +2 -2
  17. data/examples/cli_app.rb +2 -2
  18. data/examples/events.rb +3 -3
  19. data/examples/personal_access_token.rb +2 -2
  20. data/lib/asana/authentication/oauth2/access_token_authentication.rb +4 -1
  21. data/lib/asana/authentication/oauth2/bearer_token_authentication.rb +3 -2
  22. data/lib/asana/authentication/oauth2/client.rb +2 -0
  23. data/lib/asana/authentication/oauth2.rb +6 -4
  24. data/lib/asana/authentication/token_authentication.rb +3 -1
  25. data/lib/asana/authentication.rb +2 -0
  26. data/lib/asana/client/configuration.rb +6 -5
  27. data/lib/asana/client.rb +13 -11
  28. data/lib/asana/errors.rb +16 -11
  29. data/lib/asana/http_client/environment_info.rb +9 -8
  30. data/lib/asana/http_client/error_handling.rb +26 -20
  31. data/lib/asana/http_client/response.rb +2 -0
  32. data/lib/asana/http_client.rb +66 -65
  33. data/lib/asana/resource_includes/attachment_uploading.rb +6 -6
  34. data/lib/asana/resource_includes/collection.rb +4 -4
  35. data/lib/asana/resource_includes/event.rb +2 -0
  36. data/lib/asana/resource_includes/event_subscription.rb +2 -0
  37. data/lib/asana/resource_includes/events.rb +4 -1
  38. data/lib/asana/resource_includes/registry.rb +2 -0
  39. data/lib/asana/resource_includes/resource.rb +8 -5
  40. data/lib/asana/resource_includes/response_helper.rb +2 -0
  41. data/lib/asana/resources/audit_log_api.rb +42 -0
  42. data/lib/asana/resources/gen/attachments_base.rb +7 -6
  43. data/lib/asana/resources/gen/audit_log_api_base.rb +37 -0
  44. data/lib/asana/resources/gen/goal_relationships_base.rb +83 -0
  45. data/lib/asana/resources/gen/goals_base.rb +153 -0
  46. data/lib/asana/resources/gen/memberships_base.rb +71 -0
  47. data/lib/asana/resources/gen/portfolios_base.rb +3 -3
  48. data/lib/asana/resources/gen/project_briefs_base.rb +68 -0
  49. data/lib/asana/resources/gen/project_templates_base.rb +73 -0
  50. data/lib/asana/resources/gen/projects_base.rb +17 -4
  51. data/lib/asana/resources/gen/status_updates_base.rb +72 -0
  52. data/lib/asana/resources/gen/tasks_base.rb +13 -15
  53. data/lib/asana/resources/gen/teams_base.rb +41 -13
  54. data/lib/asana/resources/gen/time_periods_base.rb +47 -0
  55. data/lib/asana/resources/gen/typeahead_base.rb +2 -2
  56. data/lib/asana/resources/gen/users_base.rb +3 -4
  57. data/lib/asana/resources/gen/webhooks_base.rb +13 -0
  58. data/lib/asana/resources/gen/workspaces_base.rb +1 -1
  59. data/lib/asana/resources/goal.rb +54 -0
  60. data/lib/asana/resources/goal_relationship.rb +32 -0
  61. data/lib/asana/resources/membership.rb +20 -0
  62. data/lib/asana/resources/portfolio.rb +3 -3
  63. data/lib/asana/resources/project_brief.rb +30 -0
  64. data/lib/asana/resources/project_template.rb +36 -0
  65. data/lib/asana/resources/status_update.rb +54 -0
  66. data/lib/asana/resources/time_period.rb +30 -0
  67. data/lib/asana/resources/typeahead.rb +1 -1
  68. data/lib/asana/resources.rb +4 -4
  69. data/lib/asana/ruby2_0_0_compatibility.rb +2 -0
  70. data/lib/asana/version.rb +1 -1
  71. data/lib/asana.rb +2 -0
  72. data/package-lock.json +115 -0
  73. data/samples/attachments_sample.yaml +4 -4
  74. data/samples/audit_log_api_sample.yaml +11 -0
  75. data/samples/goal_relationships_sample.yaml +51 -0
  76. data/samples/goals_sample.yaml +101 -0
  77. data/samples/memberships_sample.yaml +41 -0
  78. data/samples/project_briefs_sample.yaml +41 -0
  79. data/samples/project_templates_sample.yaml +41 -0
  80. data/samples/projects_sample.yaml +10 -0
  81. data/samples/status_updates_sample.yaml +41 -0
  82. data/samples/teams_sample.yaml +24 -4
  83. data/samples/time_periods_sample.yaml +21 -0
  84. data/samples/webhooks_sample.yaml +10 -0
  85. metadata +75 -40
  86. data/.travis.yml +0 -16
data/asana.gemspec CHANGED
@@ -1,32 +1,34 @@
1
- # coding: utf-8
2
- lib = File.expand_path('../lib', __FILE__)
1
+ # frozen_string_literal: true
2
+
3
+ lib = File.expand_path('lib', __dir__)
3
4
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
5
  require 'asana/version'
5
6
 
6
7
  Gem::Specification.new do |spec|
7
- spec.name = "asana"
8
+ spec.name = 'asana'
8
9
  spec.version = Asana::VERSION
9
- spec.authors = ["Txus"]
10
- spec.email = ["me@txus.io"]
10
+ spec.authors = ['Txus']
11
+ spec.email = ['me@txus.io']
11
12
 
12
- spec.summary = %q{Official Ruby client for the Asana API}
13
- spec.description = %q{Official Ruby client for the Asana API}
14
- spec.homepage = "https://github.com/asana/ruby-asana"
15
- spec.license = "MIT"
13
+ spec.summary = 'Official Ruby client for the Asana API'
14
+ spec.description = 'Official Ruby client for the Asana API'
15
+ spec.homepage = 'https://github.com/asana/ruby-asana'
16
+ spec.license = 'MIT'
16
17
 
17
18
  spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
18
- spec.bindir = "exe"
19
+ spec.bindir = 'exe'
19
20
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
20
- spec.require_paths = ["lib"]
21
+ spec.require_paths = ['lib']
21
22
 
22
- spec.required_ruby_version = '> 2.0'
23
+ spec.required_ruby_version = '>= 2.7'
23
24
 
24
- spec.add_dependency "oauth2", "~> 1.4"
25
- spec.add_dependency "faraday", "~> 1.0"
26
- spec.add_dependency "faraday_middleware", "~> 1.0"
27
- spec.add_dependency "faraday_middleware-multi_json", "~> 0.0"
25
+ spec.add_dependency 'faraday', '~> 2.0'
26
+ spec.add_dependency 'faraday-follow_redirects'
27
+ spec.add_dependency 'faraday-multipart'
28
+ spec.add_dependency 'oauth2', '>= 1.4', '< 3'
28
29
 
29
- spec.add_development_dependency "rake", "~> 10.0"
30
- spec.add_development_dependency "rspec", "~> 3.2"
31
30
  spec.add_development_dependency 'appraisal', '~> 2.1', '>= 2.1'
31
+ spec.add_development_dependency 'rake', '~> 13.0'
32
+ spec.add_development_dependency 'rspec', '~> 3.2'
33
+ spec.metadata['rubygems_mfa_required'] = 'true'
32
34
  end
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: ..
3
3
  specs:
4
- asana (0.10.3)
4
+ asana (0.10.5)
5
5
  faraday (~> 1.0)
6
6
  faraday_middleware (~> 1.0)
7
7
  faraday_middleware-multi_json (~> 0.0)
@@ -27,7 +27,7 @@ GEM
27
27
  multi_json (~> 1.3)
28
28
  multi_xml (~> 0.5)
29
29
  rack (>= 1.2, < 3)
30
- rack (2.2.3)
30
+ rack (2.2.3.1)
31
31
 
32
32
  PLATFORMS
33
33
  ruby
data/examples/cli_app.rb CHANGED
@@ -17,9 +17,9 @@ client = Asana::Client.new do |c|
17
17
  end
18
18
 
19
19
  puts "My Workspaces:"
20
- client.workspaces.find_all.each do |workspace|
20
+ client.workspaces.get_workspaces.each do |workspace|
21
21
  puts "\t* #{workspace.name} - tags:"
22
- client.tags.find_by_workspace(workspace: workspace.id).each do |tag|
22
+ client.tags.get_tags_for_workspace(workspace: workspace.id).each do |tag|
23
23
  puts "\t\t- #{tag.name}"
24
24
  end
25
25
  end
data/examples/events.rb CHANGED
@@ -13,10 +13,10 @@ client = Asana::Client.new do |c|
13
13
  c.authentication :access_token, access_token
14
14
  end
15
15
 
16
- workspace = client.workspaces.find_all.first
17
- task = client.tasks.find_all(assignee: "me", workspace: workspace.id).first
16
+ workspace = client.workspaces.get_workspaces.first
17
+ task = client.tasks.get_tasks(assignee: "me", workspace: workspace.id).first
18
18
  unless task
19
- task = client.tasks.create(workspace: workspace.id, name: "Hello world!", assignee: "me")
19
+ task = client.tasks.create_task(workspace: workspace.id, name: "Hello world!", assignee: "me")
20
20
  end
21
21
 
22
22
  Thread.abort_on_exception = true
@@ -13,9 +13,9 @@ client = Asana::Client.new do |c|
13
13
  end
14
14
 
15
15
  puts "My Workspaces:"
16
- client.workspaces.find_all.each do |workspace|
16
+ client.workspaces.get_workspaces.each do |workspace|
17
17
  puts "\t* #{workspace.name} - tags:"
18
- client.tags.find_by_workspace(workspace: workspace.id).each do |tag|
18
+ client.tags.get_tags_for_workspace(workspace: workspace.id).each do |tag|
19
19
  puts "\t\t- #{tag.name}"
20
20
  end
21
21
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Asana
2
4
  module Authentication
3
5
  module OAuth2
@@ -43,7 +45,8 @@ module Asana
43
45
  # Returns nothing.
44
46
  def configure(connection)
45
47
  @token = @token.refresh! if @token.expired?
46
- connection.request :oauth2, @token.token
48
+
49
+ connection.request :authorization, 'Bearer', @token.token
47
50
  end
48
51
  end
49
52
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Asana
2
4
  module Authentication
3
5
  module OAuth2
@@ -24,8 +26,7 @@ module Asana
24
26
  #
25
27
  # Returns nothing.
26
28
  def configure(connection)
27
- connection.authorization :Bearer, @token
28
- connection.request :oauth2, token_type: 'bearer'
29
+ connection.request :authorization, 'Bearer', @token
29
30
  end
30
31
  end
31
32
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'oauth2'
2
4
 
3
5
  module Asana
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative 'oauth2/bearer_token_authentication'
2
4
  require_relative 'oauth2/access_token_authentication'
3
5
  require_relative 'oauth2/client'
@@ -31,10 +33,10 @@ module Asana
31
33
  client = Client.new(client_id: client_id,
32
34
  client_secret: client_secret,
33
35
  redirect_uri: 'urn:ietf:wg:oauth:2.0:oob')
34
- STDOUT.puts '1. Go to the following URL to authorize the ' \
35
- " application: #{client.authorize_url}"
36
- STDOUT.puts '2. Paste the authorization code here: '
37
- auth_code = STDIN.gets.chomp
36
+ $stdout.puts '1. Go to the following URL to authorize the ' \
37
+ "application: #{client.authorize_url}"
38
+ $stdout.puts '2. Paste the authorization code here: '
39
+ auth_code = $stdin.gets.chomp
38
40
  client.token_from_auth_code(auth_code)
39
41
  end
40
42
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Asana
2
4
  module Authentication
3
5
  # Public: Represents an API token authentication mechanism.
@@ -13,7 +15,7 @@ module Asana
13
15
  #
14
16
  # Returns nothing.
15
17
  def configure(connection)
16
- connection.basic_auth(@token, '')
18
+ connection.request :authorization, :basic, @token, ''
17
19
  end
18
20
  end
19
21
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative 'authentication/oauth2'
2
4
  require_relative 'authentication/token_authentication'
3
5
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Asana
2
4
  class Client
3
5
  # Internal: Represents a configuration DSL for an Asana::Client.
@@ -17,7 +19,7 @@ module Asana
17
19
  # Public: Initializes an empty configuration object.
18
20
  def initialize
19
21
  @configuration = {
20
- :log_asana_change_warnings => true
22
+ log_asana_change_warnings: true
21
23
  }
22
24
  end
23
25
 
@@ -100,7 +102,6 @@ module Asana
100
102
  #
101
103
  # Raises ArgumentError if the OAuth2 configuration arguments are invalid.
102
104
  #
103
- # rubocop:disable Metrics/MethodLength
104
105
  def oauth2(value)
105
106
  case value
106
107
  when ::OAuth2::AccessToken
@@ -111,8 +112,8 @@ module Asana
111
112
  from_bearer_token(value[:bearer_token])
112
113
  else
113
114
  error 'Invalid OAuth2 configuration: pass in either an ' \
114
- '::OAuth2::AccessToken object of your own or a hash ' \
115
- 'containing :refresh_token or :bearer_token.'
115
+ '::OAuth2::AccessToken object of your own or a hash ' \
116
+ 'containing :refresh_token or :bearer_token.'
116
117
  end
117
118
  end
118
119
 
@@ -158,7 +159,7 @@ module Asana
158
159
  end
159
160
 
160
161
  def requiring(hash, *keys)
161
- missing_keys = keys.select { |k| !hash.key?(k) }
162
+ missing_keys = keys.reject { |k| hash.key?(k) }
162
163
  missing_keys.any? && error("Missing keys: #{missing_keys.join(', ')}")
163
164
  keys.map { |k| hash[k] }
164
165
  end
data/lib/asana/client.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative 'authentication'
2
4
  require_relative 'client/configuration'
3
5
  require_relative 'resources'
@@ -59,12 +61,12 @@ module Asana
59
61
  @resource = resource
60
62
  end
61
63
 
62
- def method_missing(m, *args, **kwargs, &block)
63
- @resource.public_send(m, *([@client] + args), **kwargs, &block)
64
+ def method_missing(method_name, *args, **kwargs, &block)
65
+ @resource.public_send(method_name, *([@client] + args), **kwargs, &block)
64
66
  end
65
67
 
66
- def respond_to_missing?(m, *)
67
- @resource.respond_to?(m)
68
+ def respond_to_missing?(method_name, *)
69
+ @resource.respond_to?(method_name)
68
70
  end
69
71
  end
70
72
 
@@ -72,15 +74,15 @@ module Asana
72
74
  #
73
75
  # Yields a {Asana::Client::Configuration} object as a configuration
74
76
  # DSL. See {Asana::Client} for usage examples.
75
- def initialize
76
- config = Configuration.new.tap { |c| yield c }.to_h
77
+ def initialize(&block)
78
+ config = Configuration.new.tap(&block).to_h
77
79
  @http_client =
78
- HttpClient.new(authentication: config.fetch(:authentication),
79
- adapter: config[:faraday_adapter],
80
- user_agent: config[:user_agent],
81
- debug_mode: config[:debug_mode],
80
+ HttpClient.new(authentication: config.fetch(:authentication),
81
+ adapter: config[:faraday_adapter],
82
+ user_agent: config[:user_agent],
83
+ debug_mode: config[:debug_mode],
82
84
  log_asana_change_warnings: config[:log_asana_change_warnings],
83
- default_headers: config[:default_headers],
85
+ default_headers: config[:default_headers],
84
86
  &config[:faraday_configuration])
85
87
  end
86
88
 
data/lib/asana/errors.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Asana
2
4
  # Public: Defines the different errors that the Asana API may throw, which the
3
5
  # client code may want to catch.
@@ -19,8 +21,8 @@ module Asana
19
21
  # user could not be authenticated.
20
22
  NotAuthorized = Class.new(APIError) do
21
23
  def to_s
22
- 'Valid credentials were not provided with the request, so the API could '\
23
- 'not associate a user with the request.'
24
+ 'Valid credentials were not provided with the request, so the API could ' \
25
+ 'not associate a user with the request.'
24
26
  end
25
27
  end
26
28
 
@@ -28,8 +30,8 @@ module Asana
28
30
  # that requires a premium account (Payment Required).
29
31
  PremiumOnly = Class.new(APIError) do
30
32
  def to_s
31
- 'The endpoint that is being requested is only available to premium '\
32
- 'users.'
33
+ 'The endpoint that is being requested is only available to premium ' \
34
+ 'users.'
33
35
  end
34
36
  end
35
37
 
@@ -37,18 +39,18 @@ module Asana
37
39
  # access the requested resource or to perform the requested action on it.
38
40
  Forbidden = Class.new(APIError) do
39
41
  def to_s
40
- 'The authorization and request syntax was valid but the server is refusing '\
41
- 'to complete the request. This can happen if you try to read or write '\
42
- 'to objects or properties that the user does not have access to.'
42
+ 'The authorization and request syntax was valid but the server is refusing ' \
43
+ 'to complete the request. This can happen if you try to read or write ' \
44
+ 'to objects or properties that the user does not have access to.'
43
45
  end
44
46
  end
45
47
 
46
48
  # Public: A 404 error. Raised when the requested resource doesn't exist.
47
49
  NotFound = Class.new(APIError) do
48
50
  def to_s
49
- 'Either the request method and path supplied do not specify a known '\
50
- 'action in the API, or the object specified by the request does not '\
51
- 'exist.'
51
+ 'Either the request method and path supplied do not specify a known ' \
52
+ 'action in the API, or the object specified by the request does not ' \
53
+ 'exist.'
52
54
  end
53
55
  end
54
56
 
@@ -59,11 +61,12 @@ module Asana
59
61
  attr_accessor :phrase
60
62
 
61
63
  def initialize(phrase)
64
+ super()
62
65
  @phrase = phrase
63
66
  end
64
67
 
65
68
  def to_s
66
- "There has been an error on Asana's end. Use this unique phrase to "\
69
+ "There has been an error on Asana's end. Use this unique phrase to " \
67
70
  'identify the problem when contacting support: ' + %("#{@phrase}")
68
71
  end
69
72
  end
@@ -74,6 +77,7 @@ module Asana
74
77
  attr_accessor :errors
75
78
 
76
79
  def initialize(errors)
80
+ super()
77
81
  @errors = errors
78
82
  end
79
83
 
@@ -89,6 +93,7 @@ module Asana
89
93
  attr_accessor :retry_after_seconds
90
94
 
91
95
  def initialize(retry_after_seconds)
96
+ super()
92
97
  @retry_after_seconds = retry_after_seconds
93
98
  end
94
99
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative '../version'
2
4
  require 'openssl'
3
5
 
@@ -6,7 +8,7 @@ module Asana
6
8
  # Internal: Adds environment information to a Faraday request.
7
9
  class EnvironmentInfo
8
10
  # Internal: The default user agent to use in all requests to the API.
9
- USER_AGENT = "ruby-asana v#{Asana::VERSION}".freeze
11
+ USER_AGENT = "ruby-asana v#{Asana::VERSION}"
10
12
 
11
13
  def initialize(user_agent = nil)
12
14
  @user_agent = user_agent || USER_AGENT
@@ -19,7 +21,7 @@ module Asana
19
21
  # environment.
20
22
  def configure(builder)
21
23
  builder.headers[:user_agent] = @user_agent
22
- builder.headers[:"X-Asana-Client-Lib"] = header
24
+ builder.headers[:'X-Asana-Client-Lib'] = header
23
25
  end
24
26
 
25
27
  private
@@ -33,21 +35,20 @@ module Asana
33
35
  .map { |k, v| "#{k}=#{v}" }.join('&')
34
36
  end
35
37
 
36
- # rubocop:disable Metrics/MethodLength
37
38
  def os
38
- if RUBY_PLATFORM =~ /win32/ || RUBY_PLATFORM =~ /mingw/
39
+ case RUBY_PLATFORM
40
+ when /win32/, /mingw/
39
41
  'windows'
40
- elsif RUBY_PLATFORM =~ /linux/
42
+ when /linux/
41
43
  'linux'
42
- elsif RUBY_PLATFORM =~ /darwin/
44
+ when /darwin/
43
45
  'darwin'
44
- elsif RUBY_PLATFORM =~ /freebsd/
46
+ when /freebsd/
45
47
  'freebsd'
46
48
  else
47
49
  'unknown'
48
50
  end
49
51
  end
50
- # rubocop:enable Metrics/MethodLength
51
52
  end
52
53
  end
53
54
  end
@@ -1,4 +1,4 @@
1
- require 'multi_json'
1
+ # frozen_string_literal: true
2
2
 
3
3
  require_relative '../errors'
4
4
 
@@ -11,7 +11,7 @@ module Asana
11
11
 
12
12
  module_function
13
13
 
14
- MAX_TIMEOUTS = 5
14
+ MAX_RETRIES = 5
15
15
 
16
16
  # Public: Perform a request handling any API errors correspondingly.
17
17
  #
@@ -27,30 +27,34 @@ module Asana
27
27
  # Raises [Asana::Errors::ServerError] when there's a server problem.
28
28
  # Raises [Asana::Errors::APIError] when the API returns an unknown error.
29
29
  #
30
- # rubocop:disable all
31
- def handle(num_timeouts=0, &request)
30
+ # rubocop:disable Metrics/AbcSize
31
+ def handle(num_retries = 0, &request)
32
32
  request.call
33
33
  rescue Faraday::ClientError => e
34
34
  raise e unless e.response
35
+
35
36
  case e.response[:status]
36
- when 400 then raise invalid_request(e.response)
37
- when 401 then raise not_authorized(e.response)
38
- when 402 then raise payment_required(e.response)
39
- when 403 then raise forbidden(e.response)
40
- when 404 then raise not_found(e.response)
41
- when 412 then recover_response(e.response)
42
- when 429 then raise rate_limit_enforced(e.response)
43
- when 500 then raise server_error(e.response)
44
- else raise api_error(e.response)
37
+ when 400 then raise invalid_request(e.response)
38
+ when 401 then raise not_authorized(e.response)
39
+ when 402 then raise payment_required(e.response)
40
+ when 403 then raise forbidden(e.response)
41
+ when 404 then raise not_found(e.response)
42
+ when 412 then recover_response(e.response)
43
+ when 429 then raise rate_limit_enforced(e.response)
44
+ when 500 then raise server_error(e.response)
45
+ else raise api_error(e.response)
45
46
  end
47
+ # Retry for timeouts or 500s from Asana
48
+ rescue Faraday::ServerError => e
49
+ raise server_error(e.response) unless num_retries < MAX_RETRIES
50
+
51
+ handle(num_retries + 1, &request)
46
52
  rescue Net::ReadTimeout => e
47
- if num_timeouts < MAX_TIMEOUTS
48
- handle(num_timeouts + 1, &request)
49
- else
50
- raise e
51
- end
53
+ raise e unless num_retries < MAX_RETRIES
54
+
55
+ handle(num_retries + 1, &request)
52
56
  end
53
- # rubocop:enable all
57
+ # rubocop:enable Metrics/AbcSize
54
58
 
55
59
  # Internal: Returns an InvalidRequest exception including a list of
56
60
  # errors.
@@ -105,13 +109,15 @@ module Asana
105
109
 
106
110
  # Internal: Parser a response body from JSON.
107
111
  def body(response)
108
- MultiJson.load(response[:body])
112
+ JSON.parse(response[:body])
109
113
  end
110
114
 
115
+ # rubocop:disable Style/OpenStructUse
111
116
  def recover_response(response)
112
117
  r = response.dup.tap { |res| res[:body] = body(response) }
113
118
  Response.new(OpenStruct.new(env: OpenStruct.new(r)))
114
119
  end
120
+ # rubocop:enable Style/OpenStructUse
115
121
  end
116
122
  end
117
123
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Asana
2
4
  class HttpClient
3
5
  # Internal: Represents a response from the Asana API.