asana 0.10.3 → 2.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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.