rubeetup 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +11 -0
- data/.travis.yml +9 -0
- data/Gemfile +4 -0
- data/README.md +173 -0
- data/Rakefile +7 -0
- data/bin/console +14 -0
- data/bin/setup +7 -0
- data/lib/rubeetup/errors.rb +32 -0
- data/lib/rubeetup/request.rb +133 -0
- data/lib/rubeetup/request_builder.rb +68 -0
- data/lib/rubeetup/request_response.rb +88 -0
- data/lib/rubeetup/request_sender.rb +93 -0
- data/lib/rubeetup/requester.rb +74 -0
- data/lib/rubeetup/requests_catalog.rb +79 -0
- data/lib/rubeetup/requests_lib/meetup_catalog.json +634 -0
- data/lib/rubeetup/requests_lib/meetup_catalog.rb +33 -0
- data/lib/rubeetup/response_wrapper.rb +29 -0
- data/lib/rubeetup/utilities.rb +51 -0
- data/lib/rubeetup/version.rb +6 -0
- data/lib/rubeetup.rb +140 -0
- data/rubeetup.gemspec +33 -0
- metadata +179 -0
@@ -0,0 +1,74 @@
|
|
1
|
+
module Rubeetup
|
2
|
+
##
|
3
|
+
# @author Mike Vascelli <michele.vascelli@gmail.com>
|
4
|
+
#
|
5
|
+
# Requester instances perform requests for the user
|
6
|
+
#
|
7
|
+
class Requester
|
8
|
+
include Rubeetup::Utilities
|
9
|
+
|
10
|
+
##
|
11
|
+
# @return [Hash{Symbol=>String}] this Requester's auth data
|
12
|
+
#
|
13
|
+
attr_reader :auth
|
14
|
+
|
15
|
+
##
|
16
|
+
# @return [Symbol] the chosen request builder
|
17
|
+
#
|
18
|
+
attr_reader :request_builder
|
19
|
+
|
20
|
+
##
|
21
|
+
# @param [Hash{Symbol=>String}] args holds auth data to send with each request
|
22
|
+
# @option args [String] :key the api key
|
23
|
+
#
|
24
|
+
def initialize(args)
|
25
|
+
self.auth = args
|
26
|
+
@request_builder = Rubeetup::RequestBuilder
|
27
|
+
end
|
28
|
+
|
29
|
+
##
|
30
|
+
# Sets auth data, and validates it.
|
31
|
+
# @param [Hash{Symbol=>String}] args holds auth data to send with each request
|
32
|
+
# @option args [String] :key the api key
|
33
|
+
# @raise [Rubeetup::InvalidAuthenticationError] if the passed auth data is not a Hash,
|
34
|
+
# or if it does not include key: 'val'
|
35
|
+
#
|
36
|
+
def auth=(args)
|
37
|
+
@auth = args
|
38
|
+
validate_auth
|
39
|
+
end
|
40
|
+
|
41
|
+
|
42
|
+
##
|
43
|
+
# Performs the actual request, by dynamically creating a Request instance,
|
44
|
+
# and by then executing it.
|
45
|
+
# @param [Symbol] name request name
|
46
|
+
# @param [Array<Hash{Symbol=>String}, ...>] args holds the request options
|
47
|
+
# @return [Array<Rubeetup::ResponseWrapper>] the request response
|
48
|
+
#
|
49
|
+
def method_missing(name, *args)
|
50
|
+
merge_auth(args)
|
51
|
+
request = request_builder.compose_request(name, args)
|
52
|
+
request.execute
|
53
|
+
end
|
54
|
+
|
55
|
+
private
|
56
|
+
|
57
|
+
def validate_auth
|
58
|
+
fail Rubeetup::InvalidAuthenticationError, 'Must respond to #merge' unless
|
59
|
+
auth.respond_to? :merge
|
60
|
+
fail Rubeetup::InvalidAuthenticationError, "Requires ---> {key: /[^\s]+/}" unless
|
61
|
+
(val = auth[:key]) && present?(val)
|
62
|
+
end
|
63
|
+
|
64
|
+
# Operates on the memory referenced by args
|
65
|
+
# @note should both auth, and args have the same keys, then the keys in auth
|
66
|
+
# will overwrite those in options. This guarantees that if the user
|
67
|
+
# includes api keys while sending a request, those will be ignored.
|
68
|
+
#
|
69
|
+
def merge_auth(args)
|
70
|
+
options = args[0]
|
71
|
+
args[0] = options.respond_to?(:merge) ? options.merge(auth) : auth
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
require 'rubeetup/requests_lib/meetup_catalog'
|
2
|
+
|
3
|
+
module Rubeetup
|
4
|
+
##
|
5
|
+
# Provides an interface to an abstract catalog of all the supported requests.
|
6
|
+
# The concrete catalogs are provided in the +rubeetup/requests_lib+ folder,
|
7
|
+
# and they are fetched by #build_catalog
|
8
|
+
# @note This module expects to be mixed in to a class which implements
|
9
|
+
# the instance method +#name+.
|
10
|
+
#
|
11
|
+
module RequestsCatalog
|
12
|
+
##
|
13
|
+
# @return [Boolean] whether a +name+ entry exists in the catalog
|
14
|
+
#
|
15
|
+
def is_in_catalog?
|
16
|
+
catalog[name]
|
17
|
+
end
|
18
|
+
|
19
|
+
##
|
20
|
+
# Reads the +name+ entry in the catalog and then gets its required parameters
|
21
|
+
# @note this module expects a concrete catalog whose entries can respond to +[:options]+
|
22
|
+
# @return [Array<Symbol>] the list of all the required parameters
|
23
|
+
#
|
24
|
+
def required_options
|
25
|
+
catalog[name][:options]
|
26
|
+
end
|
27
|
+
|
28
|
+
##
|
29
|
+
# Reads the +name+ entry in the catalog and then gets its lambda to compute the request's path
|
30
|
+
# @note this module expects a concrete catalog whose entries can respond to +[:path]+
|
31
|
+
# @return [Lambda] the lambda expression to compute the path for the request
|
32
|
+
#
|
33
|
+
def request_path
|
34
|
+
path = catalog[name][:path]
|
35
|
+
eval path if path
|
36
|
+
end
|
37
|
+
|
38
|
+
##
|
39
|
+
# Reads the +name+ entry in the catalog and then gets its POST logic if defined
|
40
|
+
# @note the entry in the concrete catalog may not respond to +:[:multipart]+
|
41
|
+
# @return [Lambda] If defined, it provides the logic to encode for multipart POST
|
42
|
+
#
|
43
|
+
def request_multipart
|
44
|
+
multi = catalog[name][:multipart]
|
45
|
+
eval multi if multi
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
##
|
51
|
+
# @todo Could be fitted to take an arg, or even an attribute, to decide which
|
52
|
+
# catalog should be built dynamically...
|
53
|
+
#
|
54
|
+
def catalog
|
55
|
+
Rubeetup::RequestsCatalog.send(:build_catalog)
|
56
|
+
end
|
57
|
+
|
58
|
+
##
|
59
|
+
# Gives you the list of all the supported requests
|
60
|
+
# @return [Array<Symbol>] the complete list of supported operations
|
61
|
+
#
|
62
|
+
def self.supported_requests
|
63
|
+
build_catalog.keys
|
64
|
+
end
|
65
|
+
|
66
|
+
##
|
67
|
+
# Here we choose the catalog we want to build.
|
68
|
+
# Then we load the catalog into a class instance variable. This should speed up
|
69
|
+
# processing, but may be costly in terms of space.
|
70
|
+
# @todo analyze the situation and decide whether to load the catalog at each
|
71
|
+
# request
|
72
|
+
#
|
73
|
+
def self.build_catalog
|
74
|
+
@data ||= Rubeetup::MeetupCatalog.requests
|
75
|
+
end
|
76
|
+
|
77
|
+
private_class_method :build_catalog
|
78
|
+
end
|
79
|
+
end
|