require 'dm-core' require 'aws/s3' module DataMapper module S3 class BaseBucketConnector def initialize @s3 = AWS::S3::S3Object end def get_s3_object(instance) @s3.find(instance.s3_key) end def store(instance, file, options) @s3.store(instance.s3_key, file, options) end end class InstanceBucketConnector < BaseBucketConnector def get_s3_object(instance) s3(instance) super end def store(instance, file, options) s3(instance) super end def s3(instance) @s3.set_current_bucket_to instance.s3_bucket end end class ClassBucketConnector < BaseBucketConnector def initialize(klass, bucket_name) @class = klass @bucket_name = bucket_name super() end def get_s3_object(instance) self.s3 super end def store(instance, file, options) s3 super end def bucket AWS::S3::Bucket.find @bucket_name end def s3 @s3.set_current_bucket_to @bucket_name @s3 end end module InstanceMethods def s3 self.class.connector.get_s3_object(self) end def store_with(file, options = nil) self.class.connector.store(self, file, options) end #Shortcut method for urls - defaults to unauthenticated def url(options = {:authenticated => false}) s3.url(options) end [:value, :metadata, :about].each do |m| send :define_method, m do s3.send(m) end end end module ClassMethods #Auto-add the properties in future version def has_s3_file_at(bucket_name) @connector = ClassBucketConnector.new(self, bucket_name) class << self attr_reader :connector send :define_method, :s3 do self.connector.s3 end send :define_method, :bucket do self.connector.bucket end end send :after_class_method, :inherited do |retval, subclass| subclass.instance_variable_set "@connector", @connector end end def has_s3_file @connector = InstanceBucketConnector.new end end end Resource.append_inclusions(S3::InstanceMethods) Model.append_extensions(S3::ClassMethods) end