google-api-client 0.6.4 → 0.7.0

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 (41) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +14 -0
  3. data/Gemfile +13 -3
  4. data/README.md +133 -97
  5. data/Rakefile +1 -1
  6. data/lib/cacerts.pem +2183 -0
  7. data/lib/google/api_client/auth/compute_service_account.rb +28 -0
  8. data/lib/google/api_client/auth/file_storage.rb +87 -0
  9. data/lib/google/api_client/auth/installed_app.rb +8 -1
  10. data/lib/google/api_client/auth/jwt_asserter.rb +0 -11
  11. data/lib/google/api_client/client_secrets.rb +1 -1
  12. data/lib/google/api_client/discovery/method.rb +1 -0
  13. data/lib/google/api_client/errors.rb +11 -0
  14. data/lib/google/api_client/gzip.rb +28 -0
  15. data/lib/google/api_client/media.rb +80 -5
  16. data/lib/google/api_client/request.rb +15 -9
  17. data/lib/google/api_client/service/batch.rb +103 -0
  18. data/lib/google/api_client/service/request.rb +144 -0
  19. data/lib/google/api_client/service/resource.rb +40 -0
  20. data/lib/google/api_client/service/result.rb +162 -0
  21. data/lib/google/api_client/service/simple_file_store.rb +151 -0
  22. data/lib/google/api_client/service/stub_generator.rb +59 -0
  23. data/lib/google/api_client/service.rb +233 -0
  24. data/lib/google/api_client/service_account.rb +1 -0
  25. data/lib/google/api_client/version.rb +4 -3
  26. data/lib/google/api_client.rb +81 -42
  27. data/spec/google/api_client/batch_spec.rb +4 -4
  28. data/spec/google/api_client/discovery_spec.rb +60 -102
  29. data/spec/google/api_client/gzip_spec.rb +86 -0
  30. data/spec/google/api_client/media_spec.rb +49 -1
  31. data/spec/google/api_client/request_spec.rb +30 -0
  32. data/spec/google/api_client/result_spec.rb +3 -4
  33. data/spec/google/api_client/service_account_spec.rb +21 -0
  34. data/spec/google/api_client/service_spec.rb +586 -0
  35. data/spec/google/api_client/simple_file_store_spec.rb +137 -0
  36. data/spec/google/api_client_spec.rb +101 -3
  37. data/spec/spec_helper.rb +3 -0
  38. data/tasks/gem.rake +3 -4
  39. metadata +95 -50
  40. data/bin/google-api +0 -391
  41. /data/{CONTRIB.md → CONTRIBUTING.md} +0 -0
@@ -0,0 +1,28 @@
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
+ require 'faraday'
16
+ require 'signet/oauth_2/client'
17
+
18
+ module Google
19
+ class APIClient
20
+ class ComputeServiceAccount < Signet::OAuth2::Client
21
+ def fetch_access_token(options={})
22
+ connection = options[:connection] || Faraday.default_connection
23
+ response = connection.get 'http://metadata/computeMetadata/v1beta1/instance/service-accounts/default/token'
24
+ Signet::OAuth2.parse_json_credentials(response.body)
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,87 @@
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
+ require 'json'
16
+ require 'signet/oauth_2/client'
17
+
18
+ module Google
19
+ class APIClient
20
+ ##
21
+ # Represents cached OAuth 2 tokens stored on local disk in a
22
+ # JSON serialized file. Meant to resemble the serialized format
23
+ # http://google-api-python-client.googlecode.com/hg/docs/epy/oauth2client.file.Storage-class.html
24
+ #
25
+ class FileStorage
26
+ # @return [String] Path to the credentials file.
27
+ attr_accessor :path
28
+
29
+ # @return [Signet::OAuth2::Client] Path to the credentials file.
30
+ attr_reader :authorization
31
+
32
+ ##
33
+ # Initializes the FileStorage object.
34
+ #
35
+ # @param [String] path
36
+ # Path to the credentials file.
37
+ def initialize(path)
38
+ @path = path
39
+ self.load_credentials
40
+ end
41
+
42
+ ##
43
+ # Attempt to read in credentials from the specified file.
44
+ def load_credentials
45
+ if File.exist? self.path
46
+ File.open(self.path, 'r') do |file|
47
+ cached_credentials = JSON.load(file)
48
+ @authorization = Signet::OAuth2::Client.new(cached_credentials)
49
+ @authorization.issued_at = Time.at(cached_credentials['issued_at'])
50
+ if @authorization.expired?
51
+ @authorization.fetch_access_token!
52
+ self.write_credentials
53
+ end
54
+ end
55
+ end
56
+ end
57
+
58
+ ##
59
+ # Write the credentials to the specified file.
60
+ #
61
+ # @param [Signet::OAuth2::Client] authorization
62
+ # Optional authorization instance. If not provided, the authorization
63
+ # already associated with this instance will be written.
64
+ def write_credentials(authorization=nil)
65
+ @authorization = authorization unless authorization.nil?
66
+
67
+ unless @authorization.refresh_token.nil?
68
+ hash = {}
69
+ %w'access_token
70
+ authorization_uri
71
+ client_id
72
+ client_secret
73
+ expires_in
74
+ refresh_token
75
+ token_credential_uri'.each do |var|
76
+ hash[var] = @authorization.instance_variable_get("@#{var}")
77
+ end
78
+ hash['issued_at'] = @authorization.issued_at.to_i
79
+
80
+ File.open(self.path, 'w', 0600) do |file|
81
+ file.write(hash.to_json)
82
+ end
83
+ end
84
+ end
85
+ end
86
+ end
87
+ end
@@ -77,9 +77,13 @@ module Google
77
77
  ##
78
78
  # Request authorization. Opens a browser and waits for response.
79
79
  #
80
+ # @param [Google::APIClient::FileStorage] storage
81
+ # Optional object that responds to :write_credentials, used to serialize
82
+ # the OAuth 2 credentials after completing the flow.
83
+ #
80
84
  # @return [Signet::OAuth2::Client]
81
85
  # Authorization instance, nil if user cancelled.
82
- def authorize
86
+ def authorize(storage=nil)
83
87
  auth = @authorization
84
88
 
85
89
  server = WEBrick::HTTPServer.new(
@@ -103,6 +107,9 @@ module Google
103
107
  Launchy.open(auth.authorization_uri.to_s)
104
108
  server.start
105
109
  if @authorization.access_token
110
+ if storage.respond_to?(:write_credentials)
111
+ storage.write_credentials(@authorization)
112
+ end
106
113
  return @authorization
107
114
  else
108
115
  return nil
@@ -34,17 +34,6 @@ module Google
34
34
  # client.authorization.fetch_access_token!
35
35
  # client.execute(...)
36
36
  #
37
- # @example Deprecated version
38
- #
39
- # client = Google::APIClient.new
40
- # key = Google::APIClient::PKCS12.load_key('client.p12', 'notasecret')
41
- # service_account = Google::APIClient::JWTAsserter.new(
42
- # '123456-abcdef@developer.gserviceaccount.com',
43
- # 'https://www.googleapis.com/auth/prediction',
44
- # key)
45
- # client.authorization = service_account.authorize
46
- # client.execute(...)
47
- #
48
37
  # @deprecated
49
38
  # Service accounts are now supported directly in Signet
50
39
  # @see https://developers.google.com/accounts/docs/OAuth2ServiceAccount
@@ -146,7 +146,7 @@ module Google
146
146
  end
147
147
 
148
148
  def to_authorization
149
- gem 'signet', '~> 0.4.0'
149
+ gem 'signet', '>= 0.4.0'
150
150
  require 'signet/oauth_2/client'
151
151
  # NOTE: Do not rely on this default value, as it may change
152
152
  new_authorization = Signet::OAuth2::Client.new
@@ -187,6 +187,7 @@ module Google
187
187
  # @return [Addressable::URI] The URI after expansion.
188
188
  def generate_uri(parameters={})
189
189
  parameters = self.normalize_parameters(parameters)
190
+
190
191
  self.validate_parameters(parameters)
191
192
  template_variables = self.uri_template.variables
192
193
  upload_type = parameters.assoc('uploadType') || parameters.assoc('upload_type')
@@ -19,6 +19,17 @@ module Google
19
19
  # An error which is raised when there is an unexpected response or other
20
20
  # transport error that prevents an operation from succeeding.
21
21
  class TransmissionError < StandardError
22
+ attr_reader :result
23
+ def initialize(message = nil, result = nil)
24
+ super(message)
25
+ @result = result
26
+ end
27
+ end
28
+
29
+ ##
30
+ # An exception that is raised if a redirect is required
31
+ #
32
+ class RedirectError < TransmissionError
22
33
  end
23
34
 
24
35
  ##
@@ -0,0 +1,28 @@
1
+ require 'faraday'
2
+ require 'zlib'
3
+
4
+ module Google
5
+ class APIClient
6
+ class Gzip < Faraday::Response::Middleware
7
+ include Google::APIClient::Logging
8
+
9
+ def on_complete(env)
10
+ encoding = env[:response_headers]['content-encoding'].to_s.downcase
11
+ case encoding
12
+ when 'gzip'
13
+ logger.debug { "Decompressing gzip encoded response (#{env[:body].length} bytes)" }
14
+ env[:body] = Zlib::GzipReader.new(StringIO.new(env[:body])).read
15
+ env[:response_headers].delete('content-encoding')
16
+ logger.debug { "Decompressed (#{env[:body].length} bytes)" }
17
+ when 'deflate'
18
+ logger.debug{ "Decompressing deflate encoded response (#{env[:body].length} bytes)" }
19
+ env[:body] = Zlib::Inflate.inflate(env[:body])
20
+ env[:response_headers].delete('content-encoding')
21
+ logger.debug { "Decompressed (#{env[:body].length} bytes)" }
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+
28
+ Faraday::Response.register_middleware :gzip => Google::APIClient::Gzip
@@ -21,7 +21,11 @@ module Google
21
21
  # @see Faraday::UploadIO
22
22
  # @example
23
23
  # media = Google::APIClient::UploadIO.new('mymovie.m4v', 'video/mp4')
24
- class UploadIO < Faraday::UploadIO
24
+ class UploadIO < Faraday::UploadIO
25
+
26
+ # @return [Fixnum] Size of chunks to upload. Default is nil, meaning upload the entire file in a single request
27
+ attr_accessor :chunk_size
28
+
25
29
  ##
26
30
  # Get the length of the stream
27
31
  #
@@ -32,6 +36,77 @@ module Google
32
36
  end
33
37
  end
34
38
 
39
+ ##
40
+ # Wraps an input stream and limits data to a given range
41
+ #
42
+ # @example
43
+ # chunk = Google::APIClient::RangedIO.new(io, 0, 1000)
44
+ class RangedIO
45
+ ##
46
+ # Bind an input stream to a specific range.
47
+ #
48
+ # @param [IO] io
49
+ # Source input stream
50
+ # @param [Fixnum] offset
51
+ # Starting offset of the range
52
+ # @param [Fixnum] length
53
+ # Length of range
54
+ def initialize(io, offset, length)
55
+ @io = io
56
+ @offset = offset
57
+ @length = length
58
+ self.rewind
59
+ end
60
+
61
+ ##
62
+ # @see IO#read
63
+ def read(amount = nil, buf = nil)
64
+ buffer = buf || ''
65
+ if amount.nil?
66
+ size = @length - @pos
67
+ done = ''
68
+ elsif amount == 0
69
+ size = 0
70
+ done = ''
71
+ else
72
+ size = [@length - @pos, amount].min
73
+ done = nil
74
+ end
75
+
76
+ if size > 0
77
+ result = @io.read(size)
78
+ result.force_encoding("BINARY") if result.respond_to?(:force_encoding)
79
+ buffer << result if result
80
+ @pos = @pos + size
81
+ end
82
+
83
+ if buffer.length > 0
84
+ buffer
85
+ else
86
+ done
87
+ end
88
+ end
89
+
90
+ ##
91
+ # @see IO#rewind
92
+ def rewind
93
+ self.pos = 0
94
+ end
95
+
96
+ ##
97
+ # @see IO#pos
98
+ def pos
99
+ @pos
100
+ end
101
+
102
+ ##
103
+ # @see IO#pos=
104
+ def pos=(pos)
105
+ @pos = pos
106
+ @io.pos = @offset + pos
107
+ end
108
+ end
109
+
35
110
  ##
36
111
  # Resumable uploader.
37
112
  #
@@ -124,11 +199,11 @@ module Google
124
199
  'Content-Range' => "bytes */#{media.length}" })
125
200
  else
126
201
  start_offset = @offset
127
- self.media.io.pos = start_offset
128
- chunk = self.media.io.read(chunk_size)
129
- content_length = chunk.bytesize
202
+ remaining = self.media.length - start_offset
203
+ chunk_size = self.media.chunk_size || self.chunk_size || self.media.length
204
+ content_length = [remaining, chunk_size].min
205
+ chunk = RangedIO.new(self.media.io, start_offset, content_length)
130
206
  end_offset = start_offset + content_length - 1
131
-
132
207
  self.headers.update({
133
208
  'Content-Length' => "#{content_length}",
134
209
  'Content-Type' => self.media.content_type,
@@ -13,7 +13,7 @@
13
13
  # limitations under the License.
14
14
 
15
15
  require 'faraday'
16
- require 'faraday/utils'
16
+ require 'faraday/request/multipart'
17
17
  require 'multi_json'
18
18
  require 'compat/multi_json'
19
19
  require 'addressable/uri'
@@ -71,8 +71,10 @@ module Google
71
71
  # @option options [String, Symbol] :http_method
72
72
  # HTTP method when requesting a URI
73
73
  def initialize(options={})
74
- @parameters = Hash[options[:parameters] || {}]
74
+ @parameters = Faraday::Utils::ParamsHash.new
75
75
  @headers = Faraday::Utils::Headers.new
76
+
77
+ self.parameters.merge!(options[:parameters]) unless options[:parameters].nil?
76
78
  self.headers.merge!(options[:headers]) unless options[:headers].nil?
77
79
  self.api_method = options[:api_method]
78
80
  self.authenticated = options[:authenticated]
@@ -150,10 +152,13 @@ module Google
150
152
  #
151
153
  # @param [Faraday::Connection] connection
152
154
  # the connection to transmit with
155
+ # @param [TrueValue,FalseValue] is_retry
156
+ # True if request has been previous sent
153
157
  #
154
158
  # @return [Google::APIClient::Result]
155
159
  # result of API request
156
- def send(connection)
160
+ def send(connection, is_retry = false)
161
+ self.body.rewind if is_retry && self.body.respond_to?(:rewind)
157
162
  env = self.to_env(connection)
158
163
  logger.debug { "#{self.class} Sending API request #{env[:method]} #{env[:url].to_s} #{env[:request_headers]}" }
159
164
  http_response = connection.app.call(env)
@@ -163,8 +168,8 @@ module Google
163
168
 
164
169
  # Resumamble slightly different than other upload protocols in that it requires at least
165
170
  # 2 requests.
166
- if self.upload_type == 'resumable'
167
- upload = result.resumable_upload
171
+ if result.status == 200 && self.upload_type == 'resumable'
172
+ upload = result.resumable_upload
168
173
  unless upload.complete?
169
174
  logger.debug { "#{self.class} Sending upload body" }
170
175
  result = upload.send(connection)
@@ -282,6 +287,7 @@ module Google
282
287
  raise ArgumentError, "Can not specify body & body object for simple uploads"
283
288
  end
284
289
  self.headers['Content-Type'] ||= self.media.content_type
290
+ self.headers['Content-Length'] ||= self.media.length.to_s
285
291
  self.body = self.media
286
292
  when "multipart"
287
293
  unless options[:body_object]
@@ -314,10 +320,10 @@ module Google
314
320
  # @param [String] boundary
315
321
  # Boundary for separating each part of the message
316
322
  def build_multipart(parts, mime_type = 'multipart/related', boundary = MULTIPART_BOUNDARY)
317
- env = {
318
- :request_headers => {'Content-Type' => "#{mime_type};boundary=#{boundary}"},
319
- :request => { :boundary => boundary }
320
- }
323
+ env = Faraday::Env.new
324
+ env.request = Faraday::RequestOptions.new
325
+ env.request.boundary = boundary
326
+ env.request_headers = {'Content-Type' => "#{mime_type};boundary=#{boundary}"}
321
327
  multipart = Faraday::Request::Multipart.new
322
328
  self.body = multipart.create_multipart(env, parts.map {|part| [nil, part]})
323
329
  self.headers.update(env[:request_headers])
@@ -0,0 +1,103 @@
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
+ require 'google/api_client/service/result'
16
+ require 'google/api_client/batch'
17
+
18
+ module Google
19
+ class APIClient
20
+ class Service
21
+
22
+ ##
23
+ # Helper class to contain the result of an individual batched call.
24
+ #
25
+ class BatchedCallResult < Result
26
+ # @return [Fixnum] Index of the call
27
+ def call_index
28
+ return @base_result.response.call_id.to_i - 1
29
+ end
30
+ end
31
+
32
+ ##
33
+ #
34
+ #
35
+ class BatchRequest
36
+ ##
37
+ # Creates a new batch request.
38
+ # This class shouldn't be instantiated directly, but rather through
39
+ # Service.batch.
40
+ #
41
+ # @param [Array] calls
42
+ # List of Google::APIClient::Service::Request to be made.
43
+ # @param [Proc] block
44
+ # Callback for every call's response. Won't be called if a call
45
+ # defined a callback of its own.
46
+ #
47
+ # @yield [Google::APIClient::Service::Result]
48
+ # block to be called when result ready
49
+ def initialize(service, calls, &block)
50
+ @service = service
51
+ @base_batch = Google::APIClient::BatchRequest.new
52
+ @global_callback = block if block_given?
53
+
54
+ if calls && calls.length > 0
55
+ calls.each do |call|
56
+ add(call)
57
+ end
58
+ end
59
+ end
60
+
61
+ ##
62
+ # Add a new call to the batch request.
63
+ #
64
+ # @param [Google::APIClient::Service::Request] call
65
+ # the call to be added.
66
+ # @param [Proc] block
67
+ # callback for this call's response.
68
+ #
69
+ # @return [Google::APIClient::Service::BatchRequest]
70
+ # the BatchRequest, for chaining
71
+ #
72
+ # @yield [Google::APIClient::Service::Result]
73
+ # block to be called when result ready
74
+ def add(call, &block)
75
+ if !block_given? && @global_callback.nil?
76
+ raise BatchError, 'Request needs a block'
77
+ end
78
+ callback = block || @global_callback
79
+ base_call = {
80
+ :api_method => call.method,
81
+ :parameters => call.parameters
82
+ }
83
+ @base_batch.add(base_call) do |base_result|
84
+ result = Google::APIClient::Service::BatchedCallResult.new(
85
+ call, base_result)
86
+ callback.call(result)
87
+ end
88
+ return self
89
+ end
90
+
91
+ ##
92
+ # Executes the batch request.
93
+ def execute
94
+ @service.execute(self)
95
+ end
96
+
97
+ attr_reader :base_batch
98
+
99
+ end
100
+
101
+ end
102
+ end
103
+ end
@@ -0,0 +1,144 @@
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
@@ -0,0 +1,40 @@
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 resource.
20
+ # Simple class that contains API methods and/or child resources.
21
+ class Resource
22
+ include Google::APIClient::Service::StubGenerator
23
+
24
+ ##
25
+ # Build a resource.
26
+ # This class should not be directly instantiated in user code; resources
27
+ # are instantiated by the stub generation mechanism on Service creation.
28
+ #
29
+ # @param [Google::APIClient::Service] service
30
+ # The Service instance this resource belongs to.
31
+ # @param [Google::APIClient::API, Google::APIClient::Resource] root
32
+ # The node corresponding to this resource.
33
+ def initialize(service, root)
34
+ @service = service
35
+ generate_call_stubs(service, root)
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end