Merge pull request #188 from joekr/master
[arvados.git] / lib / google / api_client / service / request.rb
1 # Copyright 2013 Google Inc.
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 #      http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14
15 module Google
16   class APIClient
17     class Service
18       ##
19       # Handles an API request.
20       # This contains a full definition of the request to be made (including
21       # method name, parameters, body and media). The remote API call can be
22       # invoked with execute().
23       class Request
24         ##
25         # Build a request.
26         # This class should not be directly instantiated in user code;
27         # instantiation is handled by the stub methods created on Service and
28         # Resource objects.
29         #
30         # @param [Google::APIClient::Service] service
31         #   The parent Service instance that will execute the request.
32         # @param [Google::APIClient::Method] method
33         #   The Method instance that describes the API method invoked by the
34         #   request.
35         # @param [Hash] parameters
36         #   A Hash of parameter names and values to be sent in the API call.
37         def initialize(service, method, parameters)
38           @service = service
39           @method = method
40           @parameters = parameters
41           @body = nil
42           @media = nil
43
44           metaclass = (class << self; self; end)
45
46           # If applicable, add "body", "body=" and resource-named methods for
47           # retrieving and setting the HTTP body for this request.
48           # Examples of setting the body for files.insert in the Drive API:
49           #   request.body = object
50           #   request.execute
51           #  OR
52           #   request.file = object
53           #   request.execute
54           #  OR
55           #   request.body(object).execute
56           #  OR
57           #   request.file(object).execute
58           # Examples of retrieving the body for files.insert in the Drive API:
59           #   object = request.body
60           #  OR
61           #   object = request.file
62           if method.request_schema
63             body_name = method.request_schema.data['id'].dup
64             body_name[0] = body_name[0].chr.downcase
65             body_name_equals = (body_name + '=').to_sym
66             body_name = body_name.to_sym
67
68             metaclass.send(:define_method, :body) do |*args|
69               if args.length == 1
70                 @body = args.first
71                 return self
72               elsif args.length == 0
73                 return @body
74               else
75                 raise ArgumentError,
76                   "wrong number of arguments (#{args.length}; expecting 0 or 1)"
77               end
78             end
79
80             metaclass.send(:define_method, :body=) do |body|
81               @body = body
82             end
83
84             metaclass.send(:alias_method, body_name, :body)
85             metaclass.send(:alias_method, body_name_equals, :body=)
86           end
87
88           # If applicable, add "media" and "media=" for retrieving and setting
89           # the media object for this request.
90           # Examples of setting the media object:
91           #   request.media = object
92           #   request.execute
93           #  OR
94           #   request.media(object).execute
95           # Example of retrieving the media object:
96           #   object = request.media
97           if method.media_upload
98             metaclass.send(:define_method, :media) do |*args|
99               if args.length == 1
100                 @media = args.first
101                 return self
102               elsif args.length == 0
103                 return @media
104               else
105                 raise ArgumentError,
106                   "wrong number of arguments (#{args.length}; expecting 0 or 1)"
107               end
108             end
109
110             metaclass.send(:define_method, :media=) do |media|
111               @media = media
112             end
113           end
114         end
115
116         ##
117         # Returns the parent service capable of executing this request.
118         #
119         # @return [Google::APIClient::Service] The parent service.
120         attr_reader :service
121
122         ##
123         # Returns the Method instance that describes the API method invoked by
124         # the request.
125         #
126         # @return [Google::APIClient::Method] The API method description.
127         attr_reader :method
128
129         ##
130         # Contains the Hash of parameter names and values to be sent as the
131         # parameters for the API call.
132         #
133         # @return [Hash] The request parameters.
134         attr_accessor :parameters
135
136         ##
137         # Executes the request.
138         def execute
139           @service.execute(self)
140         end
141       end
142     end
143   end
144 end