nimbu-api 0.0.1

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 (66) hide show
  1. data/.gitignore +18 -0
  2. data/Gemfile +4 -0
  3. data/LICENSE.txt +22 -0
  4. data/README.md +29 -0
  5. data/Rakefile +1 -0
  6. data/lib/nimbu-api.rb +43 -0
  7. data/lib/nimbu-api/authentication.rb +76 -0
  8. data/lib/nimbu-api/builder.rb +31 -0
  9. data/lib/nimbu-api/client.rb +26 -0
  10. data/lib/nimbu-api/configuration.rb +109 -0
  11. data/lib/nimbu-api/connection.rb +88 -0
  12. data/lib/nimbu-api/endpoint.rb +199 -0
  13. data/lib/nimbu-api/endpoints/authorizations.rb +113 -0
  14. data/lib/nimbu-api/endpoints/channels.rb +31 -0
  15. data/lib/nimbu-api/endpoints/channels/entries.rb +50 -0
  16. data/lib/nimbu-api/endpoints/sites.rb +34 -0
  17. data/lib/nimbu-api/endpoints/videos.rb +26 -0
  18. data/lib/nimbu-api/errors.rb +31 -0
  19. data/lib/nimbu-api/errors/bad_request.rb +14 -0
  20. data/lib/nimbu-api/errors/client_error.rb +20 -0
  21. data/lib/nimbu-api/errors/forbidden.rb +14 -0
  22. data/lib/nimbu-api/errors/internal_server_error.rb +15 -0
  23. data/lib/nimbu-api/errors/invalid_options.rb +18 -0
  24. data/lib/nimbu-api/errors/not_acceptable.rb +15 -0
  25. data/lib/nimbu-api/errors/not_found.rb +14 -0
  26. data/lib/nimbu-api/errors/required_params.rb +18 -0
  27. data/lib/nimbu-api/errors/service_error.rb +65 -0
  28. data/lib/nimbu-api/errors/service_unavailable.rb +15 -0
  29. data/lib/nimbu-api/errors/unauthorized.rb +15 -0
  30. data/lib/nimbu-api/errors/unknown_value.rb +18 -0
  31. data/lib/nimbu-api/errors/unprocessable_entity.rb +14 -0
  32. data/lib/nimbu-api/errors/validations.rb +18 -0
  33. data/lib/nimbu-api/pagination.rb +106 -0
  34. data/lib/nimbu-api/pagination/page_iterator.rb +157 -0
  35. data/lib/nimbu-api/pagination/page_links.rb +48 -0
  36. data/lib/nimbu-api/pagination/paged_request.rb +41 -0
  37. data/lib/nimbu-api/pagination/pagination.rb +102 -0
  38. data/lib/nimbu-api/request.rb +81 -0
  39. data/lib/nimbu-api/request/arguments.rb +171 -0
  40. data/lib/nimbu-api/request/basic_auth.rb +31 -0
  41. data/lib/nimbu-api/request/json.rb +46 -0
  42. data/lib/nimbu-api/request/normalizer.rb +29 -0
  43. data/lib/nimbu-api/request/oauth2.rb +42 -0
  44. data/lib/nimbu-api/request/parameter_filter.rb +34 -0
  45. data/lib/nimbu-api/request/validations.rb +25 -0
  46. data/lib/nimbu-api/request/validations/format.rb +26 -0
  47. data/lib/nimbu-api/request/validations/presence.rb +32 -0
  48. data/lib/nimbu-api/request/validations/required.rb +26 -0
  49. data/lib/nimbu-api/request/validations/token.rb +35 -0
  50. data/lib/nimbu-api/response.rb +34 -0
  51. data/lib/nimbu-api/response/header.rb +76 -0
  52. data/lib/nimbu-api/response/json.rb +29 -0
  53. data/lib/nimbu-api/response/mashify.rb +24 -0
  54. data/lib/nimbu-api/response/raise_error.rb +18 -0
  55. data/lib/nimbu-api/response/wrapper.rb +149 -0
  56. data/lib/nimbu-api/response/xmlize.rb +26 -0
  57. data/lib/nimbu-api/utils/all.rb +6 -0
  58. data/lib/nimbu-api/utils/constants.rb +37 -0
  59. data/lib/nimbu-api/utils/descendants.rb +11 -0
  60. data/lib/nimbu-api/utils/extend_array.rb +17 -0
  61. data/lib/nimbu-api/utils/extend_hash.rb +73 -0
  62. data/lib/nimbu-api/utils/json.rb +19 -0
  63. data/lib/nimbu-api/utils/url.rb +56 -0
  64. data/lib/nimbu-api/version.rb +3 -0
  65. data/nimbu-api.gemspec +31 -0
  66. metadata +294 -0
@@ -0,0 +1,48 @@
1
+ module Nimbu
2
+ module Pagination
3
+ class PageLinks
4
+ include Nimbu::Utils::Constants
5
+
6
+ DELIM_LINKS = ",".freeze # :nodoc:
7
+
8
+ # Hold the extracted values for URI from the Link header
9
+ # for the first, last, next and previous page.
10
+ attr_accessor :first, :last, :next, :prev
11
+
12
+ # Parses links from executed request
13
+ #
14
+ def initialize(response_headers)
15
+ link_header = response_headers[HEADER_LINK]
16
+ if link_header
17
+ return unless link_header =~ /(next|first|last|prev)/
18
+
19
+ link_header.split(DELIM_LINKS).each do |link|
20
+ if link.strip =~ /<([^>]+)>; rel=\"([^\"]+)\"/
21
+ url_part, meta_part = $1, $2
22
+ next if !url_part || !meta_part
23
+ case meta_part
24
+ when META_FIRST
25
+ self.first = url_part
26
+ when META_LAST
27
+ self.last = url_part
28
+ when META_NEXT
29
+ self.next = url_part
30
+ when META_PREV
31
+ self.prev = url_part
32
+ end
33
+ end
34
+ end
35
+ else
36
+ # When on the first page
37
+ self.next = response_headers[HEADER_NEXT]
38
+ self.last = response_headers[HEADER_LAST]
39
+ end
40
+ end
41
+
42
+ def any?
43
+ self.first || self.last || self.next || self.prev
44
+ end
45
+
46
+ end # PageLinks
47
+ end # Pagination
48
+ end # Nimbu
@@ -0,0 +1,41 @@
1
+ # encoding: utf-8
2
+
3
+ module Nimbu
4
+ module Pagination
5
+ # A module that adds http get request to response pagination
6
+ module PagedRequest
7
+ include Nimbu::Utils::Constants
8
+
9
+ FIRST_PAGE = 1 # Default request page if none provided
10
+
11
+ PER_PAGE = 30 # Default number of items as specified by API
12
+
13
+ NOT_FOUND = -1 # Either page or per_page parameter not present
14
+
15
+ # Check if current api instance has default per_page param set,
16
+ # otherwise use global default.
17
+ #
18
+ def default_page_size
19
+ current_api.per_page ? current_api.per_page : PER_PAGE
20
+ end
21
+
22
+ def default_page
23
+ current_api.page ? current_api.page : FIRST_PAGE
24
+ end
25
+
26
+ # Perform http get request with paginatoin parameters
27
+ #
28
+ def page_request(path, params={})
29
+ if params[PARAM_PER_PAGE] == NOT_FOUND
30
+ params[PARAM_PER_PAGE] = default_page_size
31
+ end
32
+ if params[PARAM_PAGE] && params[PARAM_PAGE] == NOT_FOUND
33
+ params[PARAM_PAGE] = default_page
34
+ end
35
+
36
+ current_api.get_request(path, params)
37
+ end
38
+
39
+ end # PagedRequest
40
+ end # Pagination
41
+ end # Nimbu
@@ -0,0 +1,102 @@
1
+ # encoding: utf-8
2
+
3
+ module Nimbu
4
+
5
+ # A module that decorates response with pagination helpers
6
+ module Pagination
7
+ include Nimbu::Utils::Constants
8
+
9
+ # Return page links
10
+ def links
11
+ @links = Nimbu::Pagination::PageLinks.new(env[:response_headers])
12
+ end
13
+
14
+ # Retrive number of total pages base on current :per_page parameter
15
+ def count_pages
16
+ page_iterator.count.to_i
17
+ end
18
+
19
+ # Iterate over results set pages by automatically calling `next_page`
20
+ # until all pages are exhausted. Caution needs to be exercised when
21
+ # using this feature - 100 pages iteration will perform 100 API calls.
22
+ # By default this is off. You can set it on the client, individual API
23
+ # instances or just per given request.
24
+ #
25
+ def auto_paginate(auto=false)
26
+ if current_api.auto_pagination? || auto
27
+ resources_bodies = []
28
+ each_page { |resource| resources_bodies += resource.body }
29
+ self.body = resources_bodies
30
+ end
31
+ self
32
+ end
33
+
34
+ # Iterator like each for response pages. If there are no pages to
35
+ # iterate over this method will return current page.
36
+ def each_page
37
+ yield self
38
+ while page_iterator.has_next?
39
+ yield next_page
40
+ end
41
+ end
42
+
43
+ # Retrives the result of the first page. Returns <tt>nil</tt> if there is
44
+ # no first page - either because you are already on the first page
45
+ # or there are no pages at all in the result.
46
+ def first_page
47
+ first_request = page_iterator.first
48
+ self.instance_eval { @env = first_request.env } if first_request
49
+ first_request
50
+ end
51
+
52
+ # Retrives the result of the next page. Returns <tt>nil</tt> if there is
53
+ # no next page or no pages at all.
54
+ def next_page
55
+ next_request = page_iterator.next
56
+ self.instance_eval { @env = next_request.env } if next_request
57
+ next_request
58
+ end
59
+
60
+ # Retrives the result of the previous page. Returns <tt>nil</tt> if there is
61
+ # no previous page or no pages at all.
62
+ def prev_page
63
+ prev_request = page_iterator.prev
64
+ self.instance_eval { @env = prev_request.env } if prev_request
65
+ prev_request
66
+ end
67
+ alias :previous_page :prev_page
68
+
69
+ # Retrives the result of the last page. Returns <tt>nil</tt> if there is
70
+ # no last page - either because you are already on the last page,
71
+ # there is only one page or there are no pages at all in the result.
72
+ def last_page
73
+ last_request = page_iterator.last
74
+ self.instance_eval { @env = last_request.env } if last_request
75
+ last_request
76
+ end
77
+
78
+ # Retrives a specific result for a page given page number.
79
+ # The <tt>page_number</tt> parameter is not validate, hitting a page
80
+ # that does not exist will return Nimbu API error. Consequently, if
81
+ # there is only one page, this method returns nil
82
+ def page(page_number)
83
+ request = page_iterator.get_page(page_number)
84
+ self.instance_eval { @env = request.env } if request
85
+ request
86
+ end
87
+
88
+ # Returns <tt>true</tt> if there is another page in the result set,
89
+ # otherwise <tt>false</tt>
90
+ def has_next_page?
91
+ page_iterator.has_next?
92
+ end
93
+
94
+ private
95
+
96
+ # Internally used page iterator
97
+ def page_iterator # :nodoc:
98
+ @page_iterator = Nimbu::Pagination::PageIterator.new(links, current_api)
99
+ end
100
+
101
+ end # Pagination
102
+ end # Nimbu
@@ -0,0 +1,81 @@
1
+ # encoding: utf-8
2
+
3
+ require 'nimbu-api/request/oauth2'
4
+ require 'nimbu-api/request/basic_auth'
5
+ require 'nimbu-api/request/json'
6
+ require 'nimbu-api/request/validations'
7
+ require 'nimbu-api/request/arguments'
8
+
9
+ module Nimbu
10
+
11
+ # Defines HTTP verbs
12
+ module Request
13
+ include Nimbu::Utils::Constants
14
+
15
+ METHODS = [:get, :post, :put, :delete, :patch]
16
+ METHODS_WITH_BODIES = [ :post, :put, :patch ]
17
+
18
+ def get_request(path, params={}, options={})
19
+ request(:get, path, params, options)
20
+ end
21
+
22
+ def patch_request(path, params={}, options={})
23
+ request(:patch, path, params, options)
24
+ end
25
+
26
+ def post_request(path, params={}, options={})
27
+ request(:post, path, params, options)
28
+ end
29
+
30
+ def put_request(path, params={}, options={})
31
+ request(:put, path, params, options)
32
+ end
33
+
34
+ def delete_request(path, params={}, options={})
35
+ request(:delete, path, params, options)
36
+ end
37
+
38
+ def request(method, path, params, options) # :nodoc:
39
+ if !METHODS.include?(method)
40
+ raise ArgumentError, "unkown http method: #{method}"
41
+ end
42
+
43
+ puts "EXECUTED: #{method} - #{path} with #{params} and #{options}" if ENV['DEBUG']
44
+
45
+ conn = connection(options.merge(current_options))
46
+ if conn.path_prefix != '/' && path.index(conn.path_prefix) != 0
47
+ path = (conn.path_prefix + path).gsub(/\/(\/)*/, '/')
48
+ end
49
+
50
+ response = conn.send(method) do |request|
51
+ unless options[:with_attachments]
52
+ case method.to_sym
53
+ when *(METHODS - METHODS_WITH_BODIES)
54
+ request.body = params.delete('data') if params.has_key?('data')
55
+ request.url(path, params)
56
+ when *METHODS_WITH_BODIES
57
+ request.path = path
58
+ request.body = extract_data_from_params(params) unless params.empty?
59
+ end
60
+ else
61
+ request.path = path
62
+ request.body = params
63
+ end
64
+ end
65
+ Response::Wrapper.new(response, self).auto_paginate
66
+ end
67
+
68
+ private
69
+
70
+ def extract_data_from_params(params) # :nodoc:
71
+ return params['data'] if params.has_key?('data') and !params['data'].nil?
72
+ return params
73
+ end
74
+
75
+ def _extract_mime_type(params, options) # :nodoc:
76
+ options['resource'] = params['resource'] ? params.delete('resource') : ''
77
+ options['mime_type'] = params['resource'] ? params.delete('mime_type') : ''
78
+ end
79
+
80
+ end # Request
81
+ end # Nimbu
@@ -0,0 +1,171 @@
1
+ # encoding: utf-8
2
+
3
+ require 'nimbu-api/request/normalizer'
4
+ require 'nimbu-api/request/parameter_filter'
5
+
6
+ module Nimbu
7
+ module Request
8
+ # Request arguments handler
9
+ class Arguments
10
+
11
+ include Normalizer
12
+ include ParameterFilter
13
+ include Validations
14
+
15
+ AUTO_PAGINATION = 'auto_pagination'.freeze
16
+
17
+ # Parameters passed to request
18
+ attr_reader :params
19
+
20
+ attr_reader :remaining
21
+
22
+ # The request api
23
+ #
24
+ attr_reader :api
25
+
26
+ # Required arguments
27
+ #
28
+ attr_reader :required
29
+ private :required
30
+
31
+ # Optional arguments
32
+ #
33
+ attr_reader :optional
34
+ private :optional
35
+
36
+ # Takes api, filters and required arguments
37
+ #
38
+ # = Parameters
39
+ # :required - arguments that must be present before request is fired
40
+ #
41
+ def initialize(api, options={})
42
+ normalize! options
43
+ @api = api
44
+ @required = options.fetch('required', []).map(&:to_s)
45
+ @optional = options.fetch('optional', []).map(&:to_s)
46
+ end
47
+
48
+ # Parse arguments to allow for flexible api calls.
49
+ # Arguments can be part of parameters hash or be simple string arguments.
50
+ #
51
+ def parse(*args, &block)
52
+ options = args.extract_options!
53
+ normalize! options
54
+
55
+ if !args.size.zero?
56
+ parse_arguments *args
57
+ else
58
+ # Arguments are inside the parameters hash
59
+ parse_options options
60
+ end
61
+ @params = options
62
+ @remaining = extract_remaining(args)
63
+ extract_pagination(options)
64
+ yield_or_eval(&block)
65
+ self
66
+ end
67
+
68
+ # Remove unkown keys from parameters hash.
69
+ #
70
+ # = Parameters
71
+ # :recursive - boolean that toggles whether nested filtering should be applied
72
+ #
73
+ def sift(keys, key=nil, options={})
74
+ filter! keys, (key.nil? ? params : params[key]), options if keys.any?
75
+ self
76
+ end
77
+
78
+ # Check if required keys are present inside parameters hash.
79
+ #
80
+ def assert_required(required)
81
+ assert_required_keys required, params
82
+ self
83
+ end
84
+
85
+ # Check if parameters match expected values.
86
+ #
87
+ def assert_values(values, key=nil)
88
+ assert_valid_values values, (key.nil? ? params : params[key])
89
+ self
90
+ end
91
+
92
+ private
93
+
94
+ # Check and set all requried arguments.
95
+ #
96
+ def parse_arguments(*args)
97
+ assert_presence_of *args
98
+ required.each_with_index do |req, indx|
99
+ api.set req, args[indx]
100
+ end
101
+ check_requirement!(*args)
102
+ end
103
+
104
+ # Find remaining arguments
105
+ #
106
+ def extract_remaining(args)
107
+ args[required.size..-1]
108
+ end
109
+
110
+ # Fine auto_pagination parameter in options hash
111
+ #
112
+ def extract_pagination(options)
113
+ if (value = options.delete(AUTO_PAGINATION))
114
+ api.auto_pagination = value
115
+ end
116
+ end
117
+
118
+ # Remove required arguments from parameters and
119
+ # validate their presence(if not nil or empty string).
120
+ #
121
+ def parse_options(options)
122
+ options.each { |key, val| remove_required(options, key, val) }
123
+ provided_args = check_assignment!(options)
124
+ check_requirement!(*provided_args.keys)
125
+ end
126
+
127
+ # Remove required argument from parameters
128
+ #
129
+ def remove_required(options, key, val)
130
+ key = key.to_s
131
+ if required.include? key
132
+ assert_presence_of val
133
+ options.delete key
134
+ api.set key, val
135
+ end
136
+ end
137
+
138
+ # Check if required arguments have been set on instance.
139
+ #
140
+ def check_assignment!(options)
141
+ result = required.inject({}) { |hash, arg|
142
+ if api.respond_to?(:"#{arg}") && (value = api.send(:"#{arg}"))
143
+ hash[arg] = value
144
+ end
145
+ hash
146
+ }
147
+ assert_presence_of result
148
+ result
149
+ end
150
+
151
+ # Check if required arguments are present.
152
+ #
153
+ def check_requirement!(*args)
154
+ args_length = args.length
155
+ required_length = required.length
156
+
157
+ if args_length < required_length
158
+ ::Kernel.raise ArgumentError, "wrong number of arguments (#{args_length} for #{required_length})"
159
+ end
160
+ end
161
+
162
+ # Evaluate block
163
+ #
164
+ def yield_or_eval(&block)
165
+ return unless block
166
+ block.arity > 0 ? yield(self) : self.instance_eval(&block)
167
+ end
168
+
169
+ end # Arguments
170
+ end # Request
171
+ end # Nimbu