class AWS::S3::Base

AWS::S3::Base is the abstract super class of all classes who make requests against S3, such as the built in Service, Bucket and S3Object classes. It provides methods for making requests, inferring or setting response classes, processing request options, and accessing attributes from S3's response data.

Establishing a connection with the Base class is the entry point to using the library:

AWS::S3::Base.establish_connection!(:access_key_id => '...', :secret_access_key => '...')

The :access_key_id and :secret_access_key are the two required connection options. More details can be found in the docs for Connection::Management::ClassMethods.

Extensive examples can be found in the README.

Attributes

attributes[R]

Public Class Methods

current_bucket() click to toggle source

Called when a method which requires a bucket name is called without that bucket name specified. It will try to infer the current bucket by looking for it as the subdomain of the current connection's address. If no subdomain is found, CurrentBucketNotSpecified will be raised.

MusicBucket.establish_connection! :server => 'jukeboxzero.s3.amazonaws.com'
MusicBucket.connection.server
=> 'jukeboxzero.s3.amazonaws.com'
MusicBucket.current_bucket
=> 'jukeboxzero'

Rather than infering the current bucket from the subdomain, the current class' bucket can be explicitly set with set_current_bucket_to.

    # File lib/aws/s3/base.rb
106 def current_bucket
107   connection.subdomain or raise CurrentBucketNotSpecified.new(connection.http.address)
108 end
current_bucket=(name)
request(verb, path, options = {}, body = nil, attempts = 0, &block) click to toggle source

Wraps the current connection's request method and picks the appropriate response class to wrap the response in. If the response is an error, it will raise that error as an exception. All such exceptions can be caught by rescuing their superclass, the ResponseError exception class.

It is unlikely that you would call this method directly. Subclasses of Base have convenience methods for each http request verb that wrap calls to request.

   # File lib/aws/s3/base.rb
66 def request(verb, path, options = {}, body = nil, attempts = 0, &block)
67   Service.response = nil
68   process_options!(options, verb)
69   response = response_class.new(connection.request(verb, path, options, body, attempts, &block))
70   Service.response = response
71 
72   Error::Response.new(response.response).error.raise if response.error?
73   response
74 # Once in a while, a request to S3 returns an internal error. A glitch in the matrix I presume. Since these
75 # errors are few and far between the request method will rescue InternalErrors the first three times they encouter them
76 # and will retry the request again. Most of the time the second attempt will work.
77 rescue InternalError, RequestTimeout
78   if attempts == 3
79     raise
80   else
81     attempts += 1
82     retry
83   end
84 end
set_current_bucket_to(name) click to toggle source

If you plan on always using a specific bucket for certain files, you can skip always having to specify the bucket by creating a subclass of Bucket or S3Object and telling it what bucket to use:

class JukeBoxSong < AWS::S3::S3Object
  set_current_bucket_to 'jukebox'
end

For all methods that take a bucket name as an argument, the current bucket will be used if the bucket name argument is omitted.

other_song = 'baby-please-come-home.mp3'
JukeBoxSong.store(other_song, open(other_song))

This time we didn't have to explicitly pass in the bucket name, as the JukeBoxSong class knows that it will always use the 'jukebox' bucket.

“Astute readers”, as they say, may have noticed that we used the third parameter to pass in the content type, rather than the fourth parameter as we had the last time we created an object. If the bucket can be inferred, or is explicitly set, as we've done in the JukeBoxSong class, then the third argument can be used to pass in options.

Now all operations that would have required a bucket name no longer do.

other_song = JukeBoxSong.find('baby-please-come-home.mp3')
    # File lib/aws/s3/base.rb
133         def set_current_bucket_to(name)
134           raise ArgumentError, "`#{__method__}' must be called on a subclass of #{self.name}" if self == AWS::S3::Base
135           instance_eval(<<-EVAL)
136             def current_bucket
137               '#{name}'
138             end
139           EVAL
140         end
Also aliased as: current_bucket=

Private Class Methods

bucket_name(name) click to toggle source
    # File lib/aws/s3/base.rb
178 def bucket_name(name)
179   name || current_bucket
180 end
process_options!(options, verb) click to toggle source
    # File lib/aws/s3/base.rb
149 def process_options!(options, verb)
150   options.replace(RequestOptions.process(options, verb))
151 end
respond_with(klass) { || ... } click to toggle source

Using the conventions layed out in the response_class works for more than 80% of the time. There are a few edge cases though where we want a given class to wrap its responses in different response classes depending on which method is being called.

    # File lib/aws/s3/base.rb
156           def respond_with(klass)
157             eval(<<-EVAL, binding, __FILE__, __LINE__)
158               def new_response_class
159                 #{klass}
160               end
161 
162               class << self
163                 alias_method :old_response_class, :response_class
164                 alias_method :response_class, :new_response_class
165               end
166             EVAL
167 
168             yield
169           ensure
170             # Restore the original version
171             eval(<<-EVAL, binding, __FILE__, __LINE__)
172               class << self
173                 alias_method :response_class, :old_response_class
174               end
175             EVAL
176           end
response_class() click to toggle source
    # File lib/aws/s3/base.rb
145 def response_class
146   FindResponseClass.for(self)
147 end

Private Instance Methods

connection() click to toggle source
    # File lib/aws/s3/base.rb
216 def connection
217   self.class.connection
218 end
http() click to toggle source
    # File lib/aws/s3/base.rb
220 def http
221   connection.http
222 end
method_missing(method, *args, &block) click to toggle source
Calls superclass method
    # File lib/aws/s3/base.rb
228 def method_missing(method, *args, &block)
229   case
230   when attributes.has_key?(method.to_s) 
231     attributes[method.to_s]
232   when attributes.has_key?(method)
233     attributes[method]
234   else 
235     super
236   end
237 end
request(*args, &block) click to toggle source
    # File lib/aws/s3/base.rb
224 def request(*args, &block)
225   self.class.request(*args, &block)
226 end