rubeetup 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.
@@ -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