redbooth-ruby 0.0.5 → 0.1.0

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 (52) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.travis.yml +0 -1
  4. data/README.md +187 -115
  5. data/lib/redbooth-ruby/client.rb +6 -39
  6. data/lib/redbooth-ruby/client_operations/perform.rb +93 -0
  7. data/lib/redbooth-ruby/file.rb +8 -0
  8. data/lib/redbooth-ruby/helpers.rb +32 -0
  9. data/lib/redbooth-ruby/operations/base.rb +3 -2
  10. data/lib/redbooth-ruby/request/collection.rb +3 -2
  11. data/lib/redbooth-ruby/request/connection.rb +66 -30
  12. data/lib/redbooth-ruby/request/helpers.rb +2 -2
  13. data/lib/redbooth-ruby/request/info.rb +1 -1
  14. data/lib/redbooth-ruby/request/validator.rb +2 -2
  15. data/lib/redbooth-ruby/session.rb +34 -11
  16. data/lib/redbooth-ruby/task_list.rb +28 -0
  17. data/lib/redbooth-ruby/version.rb +2 -2
  18. data/lib/redbooth-ruby.rb +6 -3
  19. data/spec/cassettes/RedboothRuby_File/_download/downloads_a_file.yml +354 -0
  20. data/spec/cassettes/RedboothRuby_Organization/_delete/makes_a_new_DELETE_request_using_the_correct_API_endpoint_to_delete_a_specific_organization.yml +4 -4
  21. data/spec/cassettes/RedboothRuby_Project/_delete/makes_a_new_DELETE_request_using_the_correct_API_endpoint_to_delete_a_specific_project.yml +110 -110
  22. data/spec/cassettes/RedboothRuby_Session/_refresh_access_token_/.yml +55 -0
  23. data/spec/cassettes/RedboothRuby_Session/_refresh_access_token_/call_on_token_refresh_with_the_old_and_new_token.yml +55 -0
  24. data/spec/cassettes/RedboothRuby_Session/_refresh_access_token_/refreshes_the_access_token.yml +55 -0
  25. data/spec/redbooth-ruby/base_spec.rb +5 -5
  26. data/spec/redbooth-ruby/client_operations/metadata_spec.rb +4 -4
  27. data/spec/redbooth-ruby/client_operations/perform_spec.rb +135 -0
  28. data/spec/redbooth-ruby/client_operations/search_spec.rb +4 -4
  29. data/spec/redbooth-ruby/client_spec.rb +2 -43
  30. data/spec/redbooth-ruby/comment_spec.rb +17 -18
  31. data/spec/redbooth-ruby/conversation_spec.rb +16 -16
  32. data/spec/redbooth-ruby/file_spec.rb +29 -22
  33. data/spec/redbooth-ruby/me_spec.rb +2 -2
  34. data/spec/redbooth-ruby/membership_spec.rb +18 -18
  35. data/spec/redbooth-ruby/note_spec.rb +16 -16
  36. data/spec/redbooth-ruby/organization_spec.rb +16 -16
  37. data/spec/redbooth-ruby/person_spec.rb +18 -18
  38. data/spec/redbooth-ruby/project_spec.rb +18 -18
  39. data/spec/redbooth-ruby/request/base_spec.rb +5 -5
  40. data/spec/redbooth-ruby/request/collection_spec.rb +3 -3
  41. data/spec/redbooth-ruby/request/connection_spec.rb +8 -8
  42. data/spec/redbooth-ruby/request/info_spec.rb +13 -13
  43. data/spec/redbooth-ruby/request/response_spec.rb +4 -4
  44. data/spec/redbooth-ruby/request/validator_spec.rb +7 -7
  45. data/spec/redbooth-ruby/session_spec.rb +100 -0
  46. data/spec/redbooth-ruby/subtaks_spec.rb +16 -16
  47. data/spec/redbooth-ruby/task_spec.rb +22 -22
  48. data/spec/redbooth-ruby/user_spec.rb +4 -4
  49. data/spec/redbooth_spec.rb +13 -13
  50. data/spec/spec_helper.rb +2 -3
  51. data/temp/spec/files/test_download.txt +8 -0
  52. metadata +41 -24
@@ -2,10 +2,11 @@ module RedboothRuby
2
2
  class Client
3
3
  include RedboothRuby::ClientOperations::Search
4
4
  include RedboothRuby::ClientOperations::Metadata
5
+ include Helpers
5
6
 
6
7
  RESOURCES = [ :me, :user, :task, :organization, :person, :project,
7
8
  :conversation, :membership, :comment, :note, :subtask,
8
- :file ]
9
+ :file, :task_list ]
9
10
 
10
11
  attr_reader :session, :options
11
12
 
@@ -27,7 +28,7 @@ module RedboothRuby
27
28
  #
28
29
  # @param [String||Symbol] action name of the action to execute over
29
30
  # @param [Hash] options for the execution
30
- # @returns the execution return or nil
31
+ # @return the execution return or nil
31
32
  #
32
33
  # @example
33
34
  # session = RedboothRuby::Session.new(api_key: '_your_api_key_', auth_token: '_aut_token_for_the_user')
@@ -50,43 +51,9 @@ module RedboothRuby
50
51
  # @param [String||Symbol] resource_name name of the resource to execute over
51
52
  # @param [String||Symbol] action name of the action to execute over
52
53
  # @param [Hash] options for the execution
53
- # @returns the execution return or nil
54
+ # @return the execution return or nil
54
55
  def perform!(resource_name, action, options = {})
55
- fail RedboothRuby::AuthenticationError unless session
56
- resource(resource_name).send(action, options_with_session(options))
57
- rescue Processing => processing
58
- delay = processing.response.data["retry_after"] || 10
59
- retry_in(delay, resource_name, action, options)
56
+ ClientOperations::Perform.new(resource_name, action, session, options).perform!
60
57
  end
61
-
62
- # Retryes the request in the given time
63
- # either calls the given proc options[:retry]
64
- # or executes it in this thread
65
- #
66
- def retry_in(delay, *args)
67
- if options[:retry]
68
- options[:retry].call(delay)
69
- else
70
- sleep(delay)
71
- perform!(*args)
72
- end
73
- end
74
-
75
- # Merge the given options with the session for use the api
76
- #
77
- # @param [Hash] options options to merge with session
78
- # @return [Hash]
79
- def options_with_session(options={})
80
- options.merge(session: @session)
81
- end
82
-
83
- # Gest the api resource model class by his name
84
- #
85
- # @param [String||Symbol] name name of the resource
86
- # @return [Copy::Base] resource to use the api
87
- def resource(name)
88
- eval('RedboothRuby::' + name.to_s.capitalize) rescue nil
89
- end
90
-
91
58
  end
92
- end
59
+ end
@@ -0,0 +1,93 @@
1
+ module RedboothRuby
2
+ module ClientOperations
3
+ class Perform
4
+ include RedboothRuby::Helpers
5
+ attr_accessor :resource_name, :action, :session, :options
6
+ attr_accessor :tries, :processing_error, :oauth_token_expired_error
7
+
8
+ def initialize(resource_name, action, session, options = {})
9
+ @resource_name = resource_name
10
+ @action = action
11
+ @session = session
12
+ @options = options
13
+ @tries = 0
14
+ end
15
+
16
+ # Performs the resource action
17
+ #
18
+ # @return the execution return or nil
19
+ def perform!
20
+ @tries += 1
21
+ fail RedboothRuby::AuthenticationError unless session
22
+ resource(resource_name).send(action, options_with_session(options))
23
+ rescue Processing => processing_error
24
+ @processing_error = processing_error
25
+ perform_processing!
26
+ rescue OauthTokenExpired => oauth_token_expired_error
27
+ @oauth_token_expired_error = oauth_token_expired_error
28
+ perform_oauth_token_expired!
29
+ end
30
+
31
+ # Delays the execution of the enqueued processing
32
+ #
33
+ # @return the execution return or nil
34
+ def perform_processing!
35
+ delay = if processing_error && processing_error.response
36
+ processing_error.response.data['retry_after'].to_i
37
+ else
38
+ 10
39
+ end
40
+ retry_in(delay)
41
+ end
42
+
43
+ # Perform refresh on the session access token
44
+ #
45
+ # @return the execution return or raise OauthTokenExpired
46
+ def perform_oauth_token_expired!
47
+ if tries == 1 && refresh_session_access_token!
48
+ perform!
49
+ else
50
+ raise oauth_token_expired_error
51
+ end
52
+ end
53
+
54
+ private
55
+
56
+ # Retries the request in the given time either calls the given
57
+ # proc options[:retry] or executes it in this thread
58
+ #
59
+ def retry_in(delay)
60
+ if options[:retry]
61
+ options[:retry].call(delay)
62
+ else
63
+ sleep(delay)
64
+ perform!
65
+ end
66
+ end
67
+
68
+ # Merge the given options with the session for use the api
69
+ #
70
+ # @param [Hash] options options to merge with session
71
+ # @return [Hash]
72
+ def options_with_session(options={})
73
+ options.merge(session: @session)
74
+ end
75
+
76
+ # Get the api resource model class by his name
77
+ #
78
+ # @param [String||Symbol] name name of the resource
79
+ # @return [Copy::Base] resource to use the api
80
+ def resource(name)
81
+ Object.const_get("RedboothRuby::#{camelize(name)}") rescue nil
82
+ end
83
+
84
+ # Refresh the session access token if auto_refresh_token is enabled
85
+ #
86
+ # @return [Boolean]
87
+ def refresh_session_access_token!
88
+ session.auto_refresh_token && session.refresh_access_token!
89
+ end
90
+
91
+ end
92
+ end
93
+ end
@@ -24,6 +24,14 @@ module RedboothRuby
24
24
  :created_at,
25
25
  :updated_at
26
26
 
27
+ # Returns a blop with the file data
28
+ #
29
+ # @return [String] the object metadata
30
+ def download(style='original')
31
+ request = RedboothRuby.request(:download, nil, "files/#{id}/download/#{style}/#{name}", {}, { session: session })
32
+ request.body
33
+ end
34
+
27
35
  class << self
28
36
  # Create operation overwrite to parse file first
29
37
  def create(attrs)
@@ -0,0 +1,32 @@
1
+ module RedboothRuby
2
+ module Helpers
3
+
4
+ # Transform a resource name into a class name.
5
+ # Transform a Symbol|String:
6
+ # capitalize the first letter
7
+ # capitalize the first letter after _'s, removing the _'s
8
+ # Example: camelize(:task_list) # => TaskList
9
+ # Example: camelize('task_list') # => TaskList
10
+ #
11
+ # @param [Symbol|String] name to convert
12
+ # @return [String] string of the class name
13
+ def camelize(name)
14
+ name.to_s.gsub(/\/(.?)/) { "::#{$1.upcase}" }.gsub(/(?:^|_)(.)/) { $1.upcase }
15
+ end
16
+
17
+ # Transform a class name into a resource name.
18
+ # Downcase all the letters, inserting an underscore _ before capitals
19
+ # Example: underscore('TaskList') # => task_list
20
+ #
21
+ # @param [String] camel_case_word to convert
22
+ # @return [String] string of the resource name
23
+ def underscore(camel_case_word)
24
+ camel_case_word.gsub(/::/, '/').
25
+ gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
26
+ gsub(/([a-z\d])([A-Z])/,'\1_\2').
27
+ tr("-", "_").
28
+ downcase
29
+ end
30
+
31
+ end
32
+ end
@@ -2,6 +2,7 @@ module RedboothRuby
2
2
  module Operations
3
3
  module Base
4
4
  module ClassMethods
5
+ include RedboothRuby::Helpers
5
6
  # Options for request
6
7
  # overwrite this in the model to set security
7
8
  #
@@ -20,7 +21,7 @@ module RedboothRuby
20
21
  #
21
22
  def api_member_url(id = nil, method = nil)
22
23
  url = api_resource_name(method)
23
- url += "/#{id}" if id
24
+ url += "/#{ id }" if id
24
25
  url
25
26
  end
26
27
 
@@ -35,7 +36,7 @@ module RedboothRuby
35
36
  # overwrite this in the model if the api is not well named
36
37
  #
37
38
  def api_resource_name(method = nil)
38
- "#{name.split('::').last.downcase}s"
39
+ "#{ underscore(name.split('::').last) }s"
39
40
  end
40
41
  end
41
42
 
@@ -1,6 +1,7 @@
1
1
  module RedboothRuby
2
2
  module Request
3
3
  class Collection
4
+ include RedboothRuby::Helpers
4
5
  attr_reader :response, :params, :method, :session, :resource
5
6
 
6
7
  def initialize(attributes={})
@@ -99,12 +100,12 @@ module RedboothRuby
99
100
  klass.new(hash)
100
101
  end
101
102
 
102
- # Gest the api resource model class by his name
103
+ # Get the api resource model class by his name
103
104
  #
104
105
  # @param [String||Symbol] name name of the resource
105
106
  # @return [Copy::Base] resource to use the api
106
107
  def resource_klass(name)
107
- eval('RedboothRuby::' + name.to_s.capitalize) rescue nil
108
+ eval('RedboothRuby::' + camelize(name)) rescue nil
108
109
  end
109
110
 
110
111
  # Whenever the response is paginated or not
@@ -14,34 +14,35 @@ module RedboothRuby
14
14
 
15
15
  def request
16
16
  return unless access_token
17
- if use_body_file?
18
- ::File.open(body_file_attrs[:local_path]) do |file|
19
- req = Net::HTTP::Post::Multipart.new(
20
- api_url,
21
- body_hash.merge(
22
- 'asset' => UploadIO.new(file,
23
- 'application/octet-stream',
24
- body_file_attrs[:name]
25
- )
26
- )
27
- )
28
- req['Authorization'] = "Bearer #{access_token.token}"
29
- # access_token.sign! req
30
- if RedboothRuby.configuration[:use_ssl]
31
- http = Net::HTTP.new(RedboothRuby.configuration[:api_base] , Net::HTTP.https_default_port)
32
- http.verify_mode = OpenSSL::SSL::VERIFY_NONE
33
- http.use_ssl = RedboothRuby.configuration[:use_ssl]
34
- else
35
- domain, port = RedboothRuby.configuration[:api_base].split(':')
36
- http = Net::HTTP.new(domain, port || Net::HTTP.http_default_port)
37
- end
17
+ case
18
+ when use_body_file?
19
+ multipart_request
20
+ when download_file?
21
+ download_file_with_redirect
22
+ else
23
+ access_token.send(*request_data)
24
+ end
25
+ end
26
+
27
+ # Downloads the desired file following redirects to
28
+ # amazon s3 without authentication headers
29
+ #
30
+ def download_file_with_redirect
31
+ max_redirects = access_token.options.fetch(:max_redirects, 20)
32
+ response = access_token.send(:get, URI.encode(api_url), { redirect_count: max_redirects + 1 })
33
+ if [302, 301].include? response.status
34
+ url = response.headers['Location']
35
+ uri = URI.parse(url)
36
+ req = Net::HTTP::Get.new(uri)
37
+ http = Net::HTTP.new(uri.host , Net::HTTP.https_default_port)
38
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
39
+ http.use_ssl = RedboothRuby.configuration[:use_ssl]
38
40
  http.start do |inner_http|
39
41
  inner_http.request(req)
40
42
  end
43
+ else
44
+ response
41
45
  end
42
- else
43
- access_token.send(*request_data)
44
- end
45
46
  end
46
47
 
47
48
  def set_request_data
@@ -55,6 +56,36 @@ module RedboothRuby
55
56
 
56
57
  protected
57
58
 
59
+ # Performs a multipart request by containing given files and post data
60
+ #
61
+ # @return [Http::Request]
62
+ def multipart_request
63
+ ::File.open(body_file_attrs[:local_path]) do |file|
64
+ req = Net::HTTP::Post::Multipart.new(
65
+ api_url,
66
+ body_hash.merge(
67
+ 'asset' => UploadIO.new(file,
68
+ 'application/octet-stream',
69
+ body_file_attrs[:name]
70
+ )
71
+ )
72
+ )
73
+ req['Authorization'] = "Bearer #{access_token.token}"
74
+ # access_token.sign! req
75
+ if RedboothRuby.configuration[:use_ssl]
76
+ http = Net::HTTP.new(RedboothRuby.configuration[:api_base] , Net::HTTP.https_default_port)
77
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
78
+ http.use_ssl = RedboothRuby.configuration[:use_ssl]
79
+ else
80
+ domain, port = RedboothRuby.configuration[:api_base].split(':')
81
+ http = Net::HTTP.new(domain, port || Net::HTTP.http_default_port)
82
+ end
83
+ http.start do |inner_http|
84
+ inner_http.request(req)
85
+ end
86
+ end
87
+ end
88
+
58
89
  # Body params hash
59
90
  #
60
91
  # @return [Hash]
@@ -88,6 +119,11 @@ module RedboothRuby
88
119
  body_hash.key?(:asset)
89
120
  end
90
121
 
122
+ def download_file?
123
+ return false unless @info
124
+ @info.http_method == :download
125
+ end
126
+
91
127
  def use_url_params?
92
128
  return false unless @info
93
129
  case @info.http_method
@@ -98,12 +134,12 @@ module RedboothRuby
98
134
  end
99
135
  end
100
136
 
101
- # Returns the api url foir this request or default
137
+ # Returns the api url for this request or default
102
138
  def api_url
103
- url = "#{api_url_method}#{api_url_domain}"
104
- url += "#{RedboothRuby.configuration[:api_base]}"
105
- url += "#{api_url_path}"
106
- url += "#{api_url_version}"
139
+ url = "#{ api_url_method}#{api_url_domain }"
140
+ url += "#{ RedboothRuby.configuration[:api_base] }"
141
+ url += "#{ api_url_path }"
142
+ url += "#{ api_url_version }"
107
143
  if @info
108
144
  url += @info.url
109
145
  if use_url_params? && !body_hash.empty?
@@ -123,7 +159,7 @@ module RedboothRuby
123
159
 
124
160
  def api_url_domain
125
161
  return '' unless domain
126
- "#{domain}."
162
+ "#{ domain }."
127
163
  end
128
164
 
129
165
  def api_url_path
@@ -23,7 +23,7 @@ module RedboothRuby
23
23
  result[name.to_s] = normalize_params(value)
24
24
  when Array
25
25
  value.each_with_index do |item_value, index|
26
- result["#{name.to_s}[#{index}]"] = item_value.to_s
26
+ result["#{ name.to_s }[#{ index }]"] = item_value.to_s
27
27
  end
28
28
  else
29
29
  result[name.to_s] = value.to_s
@@ -33,4 +33,4 @@ module RedboothRuby
33
33
  end
34
34
  end
35
35
  end
36
- end
36
+ end
@@ -25,7 +25,7 @@ module RedboothRuby
25
25
  def path_with_params(path, params)
26
26
  unless params.empty?
27
27
  encoded_params = URI.encode_www_form(params)
28
- [path, encoded_params].join("?")
28
+ [path, encoded_params].join('?')
29
29
  else
30
30
  path
31
31
  end
@@ -47,9 +47,9 @@ module RedboothRuby
47
47
  def verify_authentication_header
48
48
  case raw_response.headers['WWW-Authenticate']
49
49
  when /error\=\"invalid_token\".*expired/
50
- fail OauhtTokenExpired
50
+ fail OauthTokenExpired
51
51
  when /error\=\"invalid_token\".*revoked/
52
- fail OauhtTokenRevoked
52
+ fail OauthTokenRevoked
53
53
  end
54
54
  end
55
55
 
@@ -3,18 +3,23 @@ require 'oauth2'
3
3
  module RedboothRuby
4
4
  class Session
5
5
 
6
- attr_accessor :token, :refresh_token, :access_token
6
+ attr_accessor :token, :access_token
7
+ attr_accessor :refresh_token, :expires_in, :auto_refresh_token, :on_token_refresh
7
8
  attr_accessor :consumer_key, :consumer_secret
8
9
  attr_accessor :oauth_verifier, :oauth_token
9
10
 
10
11
  OAUTH_URLS = {
11
- :site => 'https://redbooth.com/api/3',
12
- :authorize_url => 'https://redbooth.com/oauth2/authorize',
13
- :token_url => 'https://redbooth.com/oauth2/token'
12
+ site: 'https://redbooth.com/api/3',
13
+ authorize_url: 'https://redbooth.com/oauth2/authorize',
14
+ token_url: 'https://redbooth.com/oauth2/token'
14
15
  }
15
16
 
16
17
  def initialize(opts = {})
17
18
  @token = opts[:token]
19
+ @refresh_token = opts[:refresh_token]
20
+ @expires_in = opts[:expires_in]
21
+ @auto_refresh_token = opts[:auto_refresh_token] || true
22
+ @on_token_refresh = opts[:on_token_refresh]
18
23
  @consumer_key = opts[:consumer_key] || RedboothRuby.configuration[:consumer_key]
19
24
  @consumer_secret = opts[:consumer_secret] || RedboothRuby.configuration[:consumer_secret]
20
25
  @oauth_verifier = opts[:oauth_verifier]
@@ -31,16 +36,34 @@ module RedboothRuby
31
36
  end
32
37
 
33
38
  def get_access_token_url
34
- url = OAUTH_URLS[:request_token_url]
35
- url += "?oauth_verifier=#{oauth_verifier}" if oauth_verifier
36
- url += "&oauth_token=#{oauth_token}" if oauth_token
39
+ uri = URI.parse(OAUTH_URLS[:token_url])
40
+ params = URI.decode_www_form(uri.query.to_s)
41
+ params << ['oauth_verifier', oauth_verifier] if oauth_verifier
42
+ params << ['oauth_token', oauth_token] if oauth_token
43
+ uri.query = URI.encode_www_form(params) if params.size > 0
44
+ uri.to_s
37
45
  end
38
46
 
39
47
  def access_token
40
- @access_token ||= OAuth2::AccessToken.new(client, token)
48
+ @access_token ||= OAuth2::AccessToken.new(client, token,
49
+ refresh_token: refresh_token, expires_in: expires_in)
41
50
  end
42
51
 
43
- end
44
- end
45
-
52
+ def refresh_access_token!
53
+ new_access_token = access_token.refresh!
54
+ if new_access_token
55
+ on_token_refresh.call(access_token, new_access_token) if on_token_refresh.is_a?(Proc)
56
+ @access_token = new_access_token
57
+ end
58
+ new_access_token
59
+ end
46
60
 
61
+ def on_token_refresh(&block)
62
+ if block_given?
63
+ @on_token_refresh = block
64
+ else
65
+ @on_token_refresh
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,28 @@
1
+ module RedboothRuby
2
+ class TaskList < Base
3
+ include RedboothRuby::Operations::Index
4
+ include RedboothRuby::Operations::Create
5
+ include RedboothRuby::Operations::Update
6
+ include RedboothRuby::Operations::Show
7
+ include RedboothRuby::Operations::Delete
8
+ include RedboothRuby::Operations::Meta
9
+
10
+ attr_accessor :id,
11
+ :name,
12
+ :project_id,
13
+ :user_id,
14
+ :start_on,
15
+ :finish_on,
16
+ :position,
17
+ :archived,
18
+ :archived_tasks_count,
19
+ :tasks_count,
20
+ :last_comment_id,
21
+ :updated_by_id,
22
+ :metadata,
23
+ :deleted,
24
+ :completed,
25
+ :created_at,
26
+ :updated_at
27
+ end
28
+ end
@@ -1,3 +1,3 @@
1
1
  module RedboothRuby
2
- VERSION = '0.0.5'
3
- end
2
+ VERSION = '0.1.0'
3
+ end
data/lib/redbooth-ruby.rb CHANGED
@@ -15,6 +15,7 @@ module RedboothRuby
15
15
  autoload :Me, 'redbooth-ruby/me'
16
16
  autoload :User, 'redbooth-ruby/user'
17
17
  autoload :Task, 'redbooth-ruby/task'
18
+ autoload :TaskList, 'redbooth-ruby/task_list'
18
19
  autoload :Organization, 'redbooth-ruby/organization'
19
20
  autoload :Person, 'redbooth-ruby/person'
20
21
  autoload :Project, 'redbooth-ruby/project'
@@ -24,6 +25,7 @@ module RedboothRuby
24
25
  autoload :Note, 'redbooth-ruby/note'
25
26
  autoload :Subtask, 'redbooth-ruby/subtask'
26
27
  autoload :File, 'redbooth-ruby/file'
28
+ autoload :Helpers, 'redbooth-ruby/helpers'
27
29
 
28
30
 
29
31
  module Operations
@@ -47,14 +49,15 @@ module RedboothRuby
47
49
  end
48
50
 
49
51
  module ClientOperations
52
+ autoload :Perform, 'redbooth-ruby/client_operations/perform'
50
53
  autoload :Search, 'redbooth-ruby/client_operations/search'
51
54
  autoload :Metadata, 'redbooth-ruby/client_operations/metadata'
52
55
  end
53
56
 
54
57
  class RedboothError < StandardError; end
55
58
  class AuthenticationError < RedboothError; end
56
- class OauhtTokenExpired < AuthenticationError; end
57
- class OauhtTokenRevoked < AuthenticationError; end
59
+ class OauthTokenExpired < AuthenticationError; end
60
+ class OauthTokenRevoked < AuthenticationError; end
58
61
  class NotFound < RedboothError; end
59
62
  class APIError < RedboothError; end
60
63
  class ObjectNotFound < APIError; end
@@ -120,4 +123,4 @@ module RedboothRuby
120
123
  @@configuration[:api_version] ||= '3'
121
124
  @@configuration[:use_ssl] ||= true
122
125
  end
123
- end
126
+ end