thecity 0.0.2

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 (53) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +3 -0
  3. data/LICENSE.md +45 -0
  4. data/README.md +170 -0
  5. data/Rakefile +11 -0
  6. data/lib/the_city/account.rb +32 -0
  7. data/lib/the_city/api/accounts.rb +34 -0
  8. data/lib/the_city/api/client.rb +136 -0
  9. data/lib/the_city/api/events.rb +55 -0
  10. data/lib/the_city/api/groups.rb +41 -0
  11. data/lib/the_city/api/needs.rb +51 -0
  12. data/lib/the_city/api/oauth.rb +50 -0
  13. data/lib/the_city/api/prayers.rb +51 -0
  14. data/lib/the_city/api/request/multipart_with_file.rb +36 -0
  15. data/lib/the_city/api/response/parse_json.rb +27 -0
  16. data/lib/the_city/api/response/raise_error.rb +28 -0
  17. data/lib/the_city/api/topics.rb +51 -0
  18. data/lib/the_city/api/users.rb +78 -0
  19. data/lib/the_city/api/utils.rb +58 -0
  20. data/lib/the_city/arguments.rb +11 -0
  21. data/lib/the_city/base.rb +133 -0
  22. data/lib/the_city/client.rb +94 -0
  23. data/lib/the_city/collection.rb +130 -0
  24. data/lib/the_city/content.rb +29 -0
  25. data/lib/the_city/error/argument_arror.rb +8 -0
  26. data/lib/the_city/error/bad_gateway.rb +10 -0
  27. data/lib/the_city/error/bad_request.rb +10 -0
  28. data/lib/the_city/error/configuration_error.rb +8 -0
  29. data/lib/the_city/error/forbidden.rb +10 -0
  30. data/lib/the_city/error/gateway_timeout.rb +10 -0
  31. data/lib/the_city/error/internal_server_error.rb +10 -0
  32. data/lib/the_city/error/not_acceptable.rb +10 -0
  33. data/lib/the_city/error/not_found.rb +10 -0
  34. data/lib/the_city/error/service_unavailable.rb +10 -0
  35. data/lib/the_city/error/too_many_requests.rb +12 -0
  36. data/lib/the_city/error/unauthorized.rb +10 -0
  37. data/lib/the_city/error/unprocessable_entity.rb +10 -0
  38. data/lib/the_city/error.rb +66 -0
  39. data/lib/the_city/event.rb +11 -0
  40. data/lib/the_city/group.rb +6 -0
  41. data/lib/the_city/need.rb +10 -0
  42. data/lib/the_city/permissions.rb +21 -0
  43. data/lib/the_city/prayer.rb +10 -0
  44. data/lib/the_city/rate_limit.rb +17 -0
  45. data/lib/the_city/terminology.rb +39 -0
  46. data/lib/the_city/time.rb +67 -0
  47. data/lib/the_city/token.rb +16 -0
  48. data/lib/the_city/topic.rb +10 -0
  49. data/lib/the_city/user.rb +41 -0
  50. data/lib/the_city/version.rb +18 -0
  51. data/lib/the_city.rb +15 -0
  52. data/thecity.gemspec +28 -0
  53. metadata +172 -0
@@ -0,0 +1,51 @@
1
+ require 'the_city/arguments'
2
+ require 'the_city/api/utils'
3
+ require 'the_city/prayer'
4
+
5
+ module TheCity
6
+ module API
7
+ module prayers
8
+ include TheCity::API::Utils
9
+
10
+ # Posts a prayer to The City
11
+ #
12
+ # @see https://api.onthecity.org/docs
13
+ #
14
+ # @req_scope group_content
15
+ # @return [TheCity::Prayer]
16
+ # @param options [Hash] A customizable set of options.
17
+ # @option options [Integer] :group_id The id of the group you will be posting to.
18
+ # @option options [String] :title The title of the prayer.
19
+ # @option options [String] :body The body text of the prayer.
20
+ def post_prayer(options)
21
+ raise(Error::ArgumentError, "Must supply a options[:group_id] for the prayers's originating group") unless options[:group_id]
22
+ raise(Error::ArgumentError, "Title (options[:title]) required") unless options[:title]
23
+ raise(Error::ArgumentError, "Body (options[:body]) required") unless options[:body]
24
+ gid = options[:group_id] || 0
25
+ object_from_response(TheCity::Prayer, :post, "/groups/#{gid}/prayers/", options, {:client => self})
26
+ end
27
+
28
+ # Returns a prayer by id
29
+ #
30
+ # @see https://api.onthecity.org/docs
31
+ #
32
+ # @req_scope group_content
33
+ # @return [TheCity::Prayer]
34
+ # @raise [TheCity::Error::NotFound] Error raised when the prayer cannot be found.
35
+ # @overload prayer(id)
36
+ # @param id [Integer] The id of the prayer.
37
+ # @overload prayer(id, options={})
38
+ # @param id [Integer] The id of the prayer.
39
+ # @param options [Hash] A customizable set of options.
40
+ # @option options [Boolean] :force_download Forces the request to hit the server and flush the cached response
41
+ def prayer(*args)
42
+ @prayers ||= {}
43
+ arguments = TheCity::Arguments.new(args)
44
+ pid = args.shift
45
+ @prayers[pid] = nil if arguments.options.delete(:force_download)
46
+ @prayers[pid] ||= object_from_response(TheCity::Prayer, :get, "/prayers/#{pid}", arguments.options, {:client => self})
47
+ end
48
+
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,36 @@
1
+ require 'faraday'
2
+
3
+ module TheCity
4
+ module API
5
+ module Request
6
+ class MultipartWithFile < Faraday::Middleware
7
+ CONTENT_TYPE = 'Content-Type'
8
+
9
+ def call(env)
10
+ for key, value in env[:body]
11
+ if value.respond_to?(:to_io)
12
+ env[:body][key] = Faraday::UploadIO.new(value, mime_type(value.path), value.path)
13
+ end
14
+ end if env[:body].is_a?(::Hash)
15
+ @app.call(env)
16
+ end
17
+
18
+ private
19
+
20
+ def mime_type(path)
21
+ case path
22
+ when /\.jpe?g/i
23
+ 'image/jpeg'
24
+ when /\.gif$/i
25
+ 'image/gif'
26
+ when /\.png$/i
27
+ 'image/png'
28
+ else
29
+ 'application/octet-stream'
30
+ end
31
+ end
32
+
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,27 @@
1
+ require 'faraday'
2
+ require 'json'
3
+
4
+ module TheCity
5
+ module API
6
+ module Response
7
+ class ParseJson < Faraday::Response::Middleware
8
+
9
+ def parse(body)
10
+ case body
11
+ when /\A^\s*$\z/, nil
12
+ nil
13
+ else
14
+ JSON.parse(body, :symbolize_names => true)
15
+ end
16
+ end
17
+
18
+ def on_complete(env)
19
+ if respond_to?(:parse)
20
+ env[:body] = parse(env[:body]) unless [204, 301, 302, 304].include?(env[:status])
21
+ end
22
+ end
23
+
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,28 @@
1
+ require 'faraday'
2
+ require 'the_city/error/bad_gateway'
3
+ require 'the_city/error/bad_request'
4
+ require 'the_city/error/forbidden'
5
+ require 'the_city/error/gateway_timeout'
6
+ require 'the_city/error/internal_server_error'
7
+ require 'the_city/error/not_acceptable'
8
+ require 'the_city/error/not_found'
9
+ require 'the_city/error/service_unavailable'
10
+ require 'the_city/error/too_many_requests'
11
+ require 'the_city/error/unauthorized'
12
+ require 'the_city/error/unprocessable_entity'
13
+
14
+ module TheCity
15
+ module API
16
+ module Response
17
+ class RaiseError < Faraday::Response::Middleware
18
+
19
+ def on_complete(env)
20
+ status_code = env[:status].to_i
21
+ error_class = TheCity::Error.errors[status_code]
22
+ raise error_class.from_response(env) if error_class
23
+ end
24
+
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,51 @@
1
+ require 'the_city/arguments'
2
+ require 'the_city/api/utils'
3
+ require 'the_city/topic'
4
+
5
+ module TheCity
6
+ module API
7
+ module Topics
8
+ include TheCity::API::Utils
9
+
10
+ # Posts a topic to The City
11
+ #
12
+ # @see https://api.onthecity.org/docs
13
+ #
14
+ # @req_scope group_content
15
+ # @return [TheCity::Topic]
16
+ # @param options [Hash] A customizable set of options.
17
+ # @option options [Integer] :group_id The id of the group you will be posting to.
18
+ # @option options [String] :title The title of the topic.
19
+ # @option options [String] :body The body text of the topic.
20
+ def post_topic(options)
21
+ raise(Error::ArgumentError, "Must supply a options[:group_id] for the topic's originating group") unless options[:group_id]
22
+ raise(Error::ArgumentError, "Title (options[:title]) required") unless options[:title]
23
+ raise(Error::ArgumentError, "Body (options[:body]) required") unless options[:body]
24
+ gid = options[:group_id] || 0
25
+ object_from_response(TheCity::Topic, :post, "/groups/#{gid}/topics/", options, {:client => self})
26
+ end
27
+
28
+ # Returns a topic by id
29
+ #
30
+ # @see https://api.onthecity.org/docs
31
+ #
32
+ # @req_scope group_content
33
+ # @return [TheCity::Topic]
34
+ # @raise [TheCity::Error::NotFound] Error raised when the topic cannot be found.
35
+ # @overload topic(id)
36
+ # @param id [Integer] The id of the topic.
37
+ # @overload topic(id, options={})
38
+ # @param id [Integer] The id of the topic.
39
+ # @param options [Hash] A customizable set of options.
40
+ # @option options [Boolean] :force_download Forces the request to hit the server and flush the cached response
41
+ def topic(*args)
42
+ @topics ||= {}
43
+ arguments = TheCity::Arguments.new(args)
44
+ tid = args.shift
45
+ @topics[tid] = nil if arguments.options.delete(:force_download)
46
+ @topics[tid] ||= object_from_response(TheCity::Topic, :get, "/topics/#{tid}", arguments.options, {:client => self})
47
+ end
48
+
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,78 @@
1
+ require 'the_city/api/utils'
2
+
3
+ module TheCity
4
+ module API
5
+ module Users
6
+ include TheCity::API::Utils
7
+
8
+ # @see https://api.onthecity.org/docs
9
+ #
10
+ # @return [TheCity::User] The requested user.
11
+ # @raise [TheCity::Error::NotFound] Error raised when the user cannot be found.
12
+ # @req_scope user_trusted
13
+ # @overload user(id)
14
+ # @param id [Integer] The id of the user.
15
+ # @overload user(id, options={})
16
+ # @param id [Integer] The id of the user.
17
+ # @param options [Hash] A customizable set of options.
18
+ # @option options [Boolean] :force_download Forces the request to hit the server and flush the cached response
19
+ def user(*args)
20
+ @users ||= {}
21
+ arguments = TheCity::Arguments.new(args)
22
+ uid = args.shift
23
+ @users[uid] = nil if arguments.options.delete(:force_download)
24
+ @users[uid] ||= object_from_response(TheCity::User, :get, "/users/#{uid}", arguments.options, {:client => self})
25
+ end
26
+
27
+ # Returns the user associated with the current access token
28
+ #
29
+ # @see https://api.onthecity.org/docs
30
+ #
31
+ # @req_scope user_basic
32
+ # @opt_scope user_extended
33
+ # @return [TheCity::User] The authenticated user.
34
+ # @param options [Hash] A customizable set of options.
35
+ # @option options [Boolean] :force_download Forces the request to hit the server and flush the cached response
36
+ def me(options={})
37
+ @me = nil if options.delete(:force_download)
38
+ @me ||= object_from_response(TheCity::User, :get, "/me", options, {:current_user => true, :client => self})
39
+ end
40
+ alias current_user me
41
+
42
+ # Returns the permissions for the current user
43
+ #
44
+ # @see https://api.onthecity.org/docs
45
+ #
46
+ # @req_scope user_permissions
47
+ # @opt_scope group_content
48
+ # @return [TheCity::Permissions] The permission object for the current user.
49
+ # @overload permissions(options={})
50
+ # @param options [Hash] A customizable set of options.
51
+ def permissions(*args)
52
+ arguments = TheCity::Arguments.new(args)
53
+ object_from_response(TheCity::Permissions, :get, "/me/permissions", arguments.options)
54
+ end
55
+
56
+ # Returns true if the specified user exists
57
+ #
58
+ # @req_scope user_trusted
59
+ # @return [Boolean] true if the user exists, otherwise false.
60
+ # @param user [Integer, String, TheCity::User] A City user id, or object.
61
+ def user?(user)
62
+ user_id = case user
63
+ when ::Integer
64
+ user
65
+ when ::String
66
+ user.to_i
67
+ when TheCity::User
68
+ user.id
69
+ end
70
+ get("/users/#{user_id}")
71
+ true
72
+ rescue TheCity::Error::NotFound
73
+ false
74
+ end
75
+
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,58 @@
1
+ require 'the_city/arguments'
2
+ require 'the_city/collection'
3
+ require 'the_city/user'
4
+ require 'the_city/group'
5
+ require 'the_city/account'
6
+ require 'uri'
7
+
8
+ module TheCity
9
+ module API
10
+ module Utils
11
+
12
+ private
13
+
14
+ # @param klass [Class]
15
+ # @param request_method [Symbol]
16
+ # @param path [String]
17
+ # @param request_options [Hash]
18
+ # @param options [Hash]
19
+ # @return [Array]
20
+ def objects_from_response(klass, request_method, path, request_options={}, options ={})
21
+ response = send(request_method.to_sym, path, request_options)[:body]
22
+ objects_from_array(klass, response, options)
23
+ end
24
+
25
+ # @param klass [Class]
26
+ # @param array [Array]
27
+ # @return [Array]
28
+ def objects_from_array(klass, array, options={})
29
+ array.map do |element|
30
+ klass.new(element, options)
31
+ end
32
+ end
33
+
34
+ # @param klass [Class]
35
+ # @param request_method [Symbol]
36
+ # @param path [String]
37
+ # @param request_options [Hash]
38
+ # @param options [Hash]
39
+ # @return [Object]
40
+ def object_from_response(klass, request_method, path, request_options={}, options ={})
41
+ response = send(request_method.to_sym, path, request_options)
42
+ klass.from_response(response, options)
43
+ end
44
+
45
+ # @param collection_name [Symbol]
46
+ # @param klass [Class]
47
+ # @param request_method [Symbol]
48
+ # @param path [String]
49
+ # @param request_options [Hash]
50
+ # @return [TheCity::Collection]
51
+ def collection_from_response(collection_name, klass, request_method, path, request_options)
52
+ response = send(request_method.to_sym, path, request_options)
53
+ TheCity::Collection.from_response(response, collection_name.to_sym, klass, self, request_method, path, request_options)
54
+ end
55
+
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,11 @@
1
+ module TheCity
2
+ class Arguments < Array
3
+ attr_reader :options
4
+
5
+ def initialize(args)
6
+ @options = args.last.is_a?(::Hash) ? args.pop : {}
7
+ super(args)
8
+ end
9
+
10
+ end
11
+ end
@@ -0,0 +1,133 @@
1
+ require 'forwardable'
2
+ require 'uri'
3
+
4
+ module TheCity
5
+ class Base
6
+ extend Forwardable
7
+ attr_reader :attrs
8
+ alias to_h attrs
9
+ alias to_hash attrs
10
+ alias to_hsh attrs
11
+ def_delegators :attrs, :delete, :update
12
+
13
+ # Define methods that retrieve the value from attributes
14
+ #
15
+ # @param attrs [Array, Symbol]
16
+ def self.attr_reader(*attrs)
17
+ for attr in attrs
18
+ define_attribute_method(attr)
19
+ define_predicate_method(attr)
20
+ end
21
+ end
22
+
23
+ # Define object methods from attributes
24
+ #
25
+ # @param klass [Symbol]
26
+ # @param key1 [Symbol]
27
+ # @param key2 [Symbol]
28
+ def self.object_attr_reader(klass, key1, key2=nil)
29
+ define_attribute_method(key1, klass, key2)
30
+ define_predicate_method(key1)
31
+ end
32
+
33
+ # Define URI methods from attributes
34
+ #
35
+ # @param attrs [Array, Symbol]
36
+ def self.uri_attr_reader(*attrs)
37
+ for uri_key in attrs
38
+ array = uri_key.to_s.split("_")
39
+ index = array.index("uri")
40
+ array[index] = "url"
41
+ url_key = array.join("_").to_sym
42
+ define_uri_method(uri_key, url_key)
43
+ define_predicate_method(uri_key, url_key)
44
+ alias_method(url_key, uri_key)
45
+ alias_method("#{url_key}?", "#{uri_key}?")
46
+ end
47
+ end
48
+
49
+ # Dynamically define a method for a URI
50
+ #
51
+ # @param key1 [Symbol]
52
+ # @param key2 [Symbol]
53
+ def self.define_uri_method(key1, key2)
54
+ define_method(key1) do
55
+ memoize(key1) do
56
+ ::URI.parse(@attrs[key2]) if @attrs[key2]
57
+ end
58
+ end
59
+ end
60
+
61
+ # Dynamically define a method for an attribute
62
+ #
63
+ # @param key1 [Symbol]
64
+ # @param klass [Symbol]
65
+ # @param key2 [Symbol]
66
+ def self.define_attribute_method(key1, klass=nil, key2=nil)
67
+ define_method(key1) do
68
+
69
+ memoize(key1) do
70
+ if klass.nil?
71
+ @attrs[key1]
72
+ else
73
+ if @attrs[key1]
74
+ if key2.nil?
75
+ TheCity.const_get(klass).new(@attrs[key1])
76
+ else
77
+ attrs = @attrs.dup
78
+ value = attrs.delete(key1)
79
+ TheCity.const_get(klass).new(value.update(key2 => attrs))
80
+ end
81
+ else
82
+ TheCity::NullObject.instance
83
+ end
84
+ end
85
+ end
86
+ end
87
+ end
88
+
89
+ # Dynamically define a predicate method for an attribute
90
+ #
91
+ # @param key1 [Symbol]
92
+ # @option key2 [Symbol]
93
+ def self.define_predicate_method(key1, key2=key1)
94
+ define_method(:"#{key1}?") do
95
+ !!@attrs[key2]
96
+ end
97
+ end
98
+
99
+ # Construct an object from a response hash
100
+ #
101
+ # @param response [Hash]
102
+ # @return [TheCity::Base]
103
+ def self.from_response(response, options)
104
+ new(response[:body], options)
105
+ end
106
+
107
+ # Initializes a new object
108
+ #
109
+ # @param attrs [Hash]
110
+ # @return [TheCity::Base]
111
+ def initialize(attrs={}, options={})
112
+ @attrs = attrs || {}
113
+ @client = options.delete(:client) rescue nil
114
+ end
115
+
116
+ # Fetches an attribute of an object using hash notation
117
+ #
118
+ # @param method [String, Symbol] Message to send to the object
119
+ def [](method)
120
+ send(method.to_sym)
121
+ rescue NoMethodError
122
+ nil
123
+ end
124
+
125
+ def memoize(key, &block)
126
+ ivar = :"@#{key}"
127
+ return instance_variable_get(ivar) if instance_variable_defined?(ivar)
128
+ result = block.call
129
+ instance_variable_set(ivar, result)
130
+ end
131
+
132
+ end
133
+ end
@@ -0,0 +1,94 @@
1
+ require 'the_city/version'
2
+ require 'uri'
3
+
4
+ module TheCity
5
+ class Client
6
+ attr_writer :access_token, :app_id, :app_secret, :subdomain, :version
7
+ alias oauth_token= access_token=
8
+
9
+ # Initializes a new Client object
10
+ #
11
+ # @param options [Hash]
12
+ # @return [TheCity::API::Client]
13
+ def initialize(options={})
14
+ for key, value in options
15
+ send(:"#{key}=", value)
16
+ end
17
+ yield self if block_given?
18
+ end
19
+
20
+ # @return [String]
21
+ def subdomain
22
+ if instance_variable_defined?(:@subdomain)
23
+ @subdomain
24
+ else
25
+ ENV['THECITY_SUBDOMAIN']
26
+ end
27
+ end
28
+
29
+ # @return [String]
30
+ def app_id
31
+ if instance_variable_defined?(:@app_id)
32
+ @app_id
33
+ else
34
+ ENV['THECITY_APP_ID']
35
+ end
36
+ end
37
+
38
+ # @return [String]
39
+ def app_secret
40
+ if instance_variable_defined?(:@app_secret)
41
+ @app_secret
42
+ else
43
+ ENV['THECITY_APP_SECRET']
44
+ end
45
+ end
46
+
47
+ # @return [String]
48
+ def access_token
49
+ if instance_variable_defined?(:@access_token)
50
+ @access_token
51
+ else
52
+ ENV['THECITY_ACCESS_TOKEN']
53
+ end
54
+ end
55
+ alias oauth_token access_token
56
+
57
+ # @return [String]
58
+ def version
59
+ if instance_variable_defined?(:@version)
60
+ @api_version || "1"
61
+ elsif ENV['THECITY_API_VERSION']
62
+ ENV['THECITY_API_VERSION']
63
+ else
64
+ "1"
65
+ end
66
+ end
67
+ alias api_version version
68
+
69
+ # @return [Hash]
70
+ def credentials
71
+ {
72
+ :app_id => app_id,
73
+ :app_secret => app_secret,
74
+ :token => access_token,
75
+ }
76
+ end
77
+
78
+ # @return [Boolean]
79
+ def credentials?
80
+ credentials.values.all?
81
+ end
82
+
83
+ private
84
+
85
+ # Ensures that all credentials set during configuration are of a
86
+ # valid type. Valid types are String and Symbol.
87
+ def validate_credentials!
88
+ for credential, value in credentials
89
+ raise(Error::ConfigurationError, "Invalid #{credential} specified: #{value.inspect} must be a string or symbol.") unless value.is_a?(String) || value.is_a?(Symbol)
90
+ end
91
+ end
92
+
93
+ end
94
+ end
@@ -0,0 +1,130 @@
1
+ module TheCity
2
+ # Utility class for collections with paged responses
3
+ class Collection
4
+ include Enumerable
5
+ attr_reader :attrs
6
+ alias to_h attrs
7
+ alias to_hash attrs
8
+ alias to_hsh attrs
9
+
10
+ # Construct a new Collection object from a response hash
11
+ #
12
+ # @param response [Hash]
13
+ # @param key [String, Symbol] The key to fetch the data from the response
14
+ # @param klass [Class] The class to instantiate objects in the response
15
+ # @param client [TheCity::API::Client]
16
+ # @param request_method [String, Symbol]
17
+ # @param path [String]
18
+ # @param options [Hash]
19
+ # @return [TheCity::Collection]
20
+ def self.from_response(response, key, klass, client, request_method, path, options)
21
+ new(response[:body], key, klass, client, request_method, path, options)
22
+ end
23
+
24
+ # Initializes a new Collection
25
+ #
26
+ # @param attrs [Hash]
27
+ # @param key [String, Symbol] The key to fetch the data from the response
28
+ # @param klass [Class] The class to instantiate objects in the response
29
+ # @param client [TheCity::API::Client]
30
+ # @param request_method [String, Symbol]
31
+ # @param path [String]
32
+ # @param options [Hash]
33
+ # @return [TheCity::Collection]
34
+ def initialize(attrs, key, klass, client, request_method, path, options)
35
+ @key = key.to_sym
36
+ @klass = klass
37
+ @client = client
38
+ @request_method = request_method.to_sym
39
+ @path = path
40
+ @options = options
41
+ @collection = []
42
+ set_attrs(attrs)
43
+ end
44
+
45
+ # @return [Enumerator]
46
+ def each(start = 0, &block)
47
+ return to_enum(:each) unless block_given?
48
+ for element in Array(@collection[start..-1])
49
+ yield element
50
+ @current_cursor += 1
51
+ end
52
+ unless last?
53
+ start = [@collection.size, start].max
54
+ fetch_next_page unless last_page?
55
+ each(start, &block)
56
+ end
57
+ @current_cursor = 1
58
+ self
59
+ end
60
+
61
+ def current_cursor
62
+ @current_cursor
63
+ end
64
+
65
+ def next_cursur
66
+ (current_cursor + 1) || -1
67
+ end
68
+ alias next next_cursur
69
+
70
+ def previous_cursor
71
+ current_cursor - 1
72
+ end
73
+ alias previous previous_cursor
74
+
75
+ # @return [Boolean]
76
+ def first?
77
+ previous_cursor.zero?
78
+ end
79
+
80
+ # @return [Boolean]
81
+ def last?
82
+ current_cursor >= total_entries
83
+ end
84
+
85
+ def current_page
86
+ @current_page
87
+ end
88
+
89
+ def next_page
90
+ current_page + 1
91
+ end
92
+
93
+ def last_page?
94
+ current_page == @total_pages
95
+ end
96
+
97
+ def total_entries
98
+ @total_entries.is_a?(Array) ? @total_entries.first : @total_entries
99
+ end
100
+ alias total total_entries
101
+
102
+ def [](n)
103
+ @collection[n]
104
+ end
105
+
106
+ def last
107
+ @collection.last
108
+ end
109
+
110
+ private
111
+
112
+ def fetch_next_page
113
+ response = @client.send(@request_method, @path, @options.merge(:page => next_page, :per_page => @per_page))
114
+ set_attrs(response[:body])
115
+ end
116
+
117
+ def set_attrs(attrs)
118
+ @attrs = attrs
119
+ for element in Array(attrs[@key])
120
+ @collection << (@klass ? @klass.new(element) : element)
121
+ end
122
+ @total_entries = attrs[:total_entries],
123
+ @current_page = attrs[:current_page],
124
+ @total_pages = attrs[:total_pages],
125
+ @per_page = attrs[:per_page],
126
+ @current_cursor = ((@current_page - 1) * @per_page) + 1
127
+ end
128
+
129
+ end
130
+ end