X-Git-Url: https://projects.mako.cc/source/selectricity-live/blobdiff_plain/a38724bea6c09b479a93948b6ef4ef61edd24f39..e75d29998f5348be83dde4b6fd8f5aa437c2dc74:/vendor/plugins/attachment_fu/lib/technoweenie/attachment_fu/backends/cloud_file_backend.rb diff --git a/vendor/plugins/attachment_fu/lib/technoweenie/attachment_fu/backends/cloud_file_backend.rb b/vendor/plugins/attachment_fu/lib/technoweenie/attachment_fu/backends/cloud_file_backend.rb new file mode 100644 index 0000000..214ab27 --- /dev/null +++ b/vendor/plugins/attachment_fu/lib/technoweenie/attachment_fu/backends/cloud_file_backend.rb @@ -0,0 +1,211 @@ +module Technoweenie # :nodoc: + module AttachmentFu # :nodoc: + module Backends + # = CloudFiles Storage Backend + # + # Enables use of {Rackspace Cloud Files}[http://www.mosso.com/cloudfiles.jsp] as a storage mechanism + # + # Based heavily on the Amazon S3 backend. + # + # == Requirements + # + # Requires the {Cloud Files Gem}[http://www.mosso.com/cloudfiles.jsp] by Rackspace + # + # == Configuration + # + # Configuration is done via RAILS_ROOT/config/rackspace_cloudfiles.yml and is loaded according to the RAILS_ENV. + # The minimum connection options that you must specify are a container name, your Mosso login name and your Mosso API key. + # You can sign up for Cloud Files and get access keys by visiting https://www.mosso.com/buy.htm + # + # Example configuration (RAILS_ROOT/config/rackspace_cloudfiles.yml) + # + # development: + # container_name: appname_development + # username: + # api_key: + # + # test: + # container_name: appname_test + # username: + # api_key: + # + # production: + # container_name: appname + # username: + # apik_key: + # + # You can change the location of the config path by passing a full path to the :cloudfiles_config_path option. + # + # has_attachment :storage => :cloud_files, :cloudfiles_config_path => (RAILS_ROOT + '/config/mosso.yml') + # + # === Required configuration parameters + # + # * :username - The username for your Rackspace Cloud (Mosso) account. Provided by Rackspace. + # * :secret_access_key - The api key for your Rackspace Cloud account. Provided by Rackspace. + # * :container_name - The name of a container in your Cloud Files account. + # + # If any of these required arguments is missing, a AuthenticationException will be raised from CloudFiles::Connection. + # + # == Usage + # + # To specify Cloud Files as the storage mechanism for a model, set the acts_as_attachment :storage option to :cloud_files/tt>. + # + # class Photo < ActiveRecord::Base + # has_attachment :storage => :cloud_files + # end + # + # === Customizing the path + # + # By default, files are prefixed using a pseudo hierarchy in the form of :table_name/:id, which results + # in Cloud Files object names (and urls) that look like: http://:server/:container_name/:table_name/:id/:filename with :table_name + # representing the customizable portion of the path. You can customize this prefix using the :path_prefix + # option: + # + # class Photo < ActiveRecord::Base + # has_attachment :storage => :cloud_files, :path_prefix => 'my/custom/path' + # end + # + # Which would result in public URLs like http(s)://:server/:container_name/my/custom/path/:id/:filename. + # + # === Permissions + # + # File permisisons are determined by the permissions of the container. At present, the options are public (and distributed + # by the Limelight CDN), and private (only available to your login) + # + # === Other options + # + # Of course, all the usual configuration options apply, such as content_type and thumbnails: + # + # class Photo < ActiveRecord::Base + # has_attachment :storage => :cloud_files, :content_type => ['application/pdf', :image], :resize_to => 'x50' + # has_attachment :storage => :cloud_files, :thumbnails => { :thumb => [50, 50], :geometry => 'x50' } + # end + # + # === Accessing Cloud Files URLs + # + # You can get an object's public URL using the cloudfiles_url accessor. For example, assuming that for your postcard app + # you had a container name like 'postcard_world_development', and an attachment model called Photo: + # + # @postcard.cloudfiles_url # => http://cdn.cloudfiles.mosso.com/c45182/uploaded_files/20/london.jpg + # + # The resulting url is in the form: http://:server/:container_name/:table_name/:id/:file. + # The optional thumbnail argument will output the thumbnail's filename (if any). + # + # Additionally, you can get an object's base path relative to the container root using + # base_path: + # + # @photo.file_base_path # => uploaded_files/20 + # + # And the full path (including the filename) using full_filename: + # + # @photo.full_filename # => uploaded_files/20/london.jpg + # + # Niether base_path or full_filename include the container name as part of the path. + # You can retrieve the container name using the container_name method. + module CloudFileBackend + class RequiredLibraryNotFoundError < StandardError; end + class ConfigFileNotFoundError < StandardError; end + + def self.included(base) #:nodoc: + mattr_reader :container_name, :cloudfiles_config + + begin + require 'cloudfiles' + rescue LoadError + raise RequiredLibraryNotFoundError.new('CloudFiles could not be loaded') + end + + begin + @@cloudfiles_config_path = base.attachment_options[:cloudfiles_config_path] || (RAILS_ROOT + '/config/rackspace_cloudfiles.yml') + @@cloudfiles_config = @@cloudfiles_config = YAML.load(ERB.new(File.read(@@cloudfiles_config_path)).result)[RAILS_ENV].symbolize_keys + rescue + #raise ConfigFileNotFoundError.new('File %s not found' % @@cloudfiles_config_path) + end + + @@container_name = @@cloudfiles_config[:container_name] + @@cf = CloudFiles::Connection.new(@@cloudfiles_config[:username], @@cloudfiles_config[:api_key]) + @@container = @@cf.container(@@container_name) + + base.before_update :rename_file + end + + # Overwrites the base filename writer in order to store the old filename + def filename=(value) + @old_filename = filename unless filename.nil? || @old_filename + write_attribute :filename, sanitize_filename(value) + end + + # The attachment ID used in the full path of a file + def attachment_path_id + ((respond_to?(:parent_id) && parent_id) || id).to_s + end + + # The pseudo hierarchy containing the file relative to the container name + # Example: :table_name/:id + def base_path + File.join(attachment_options[:path_prefix], attachment_path_id) + end + + # The full path to the file relative to the container name + # Example: :table_name/:id/:filename + def full_filename(thumbnail = nil) + File.join(base_path, thumbnail_name_for(thumbnail)) + end + + # All public objects are accessible via a GET request to the Cloud Files servers. You can generate a + # url for an object using the cloudfiles_url method. + # + # @photo.cloudfiles_url + # + # The resulting url is in the CDN URL for the object + # + # The optional thumbnail argument will output the thumbnail's filename (if any). + # + # If you are trying to get the URL for a nonpublic container, nil will be returned. + def cloudfiles_url(thumbnail = nil) + if @@container.public? + File.join(@@container.cdn_url, full_filename(thumbnail)) + else + nil + end + end + alias :public_filename :cloudfiles_url + + def create_temp_file + write_to_temp_file current_data + end + + def current_data + @@container.get_object(full_filename).data + end + + protected + # Called in the after_destroy callback + def destroy_file + @@container.delete_object(full_filename) + end + + def rename_file + # Cloud Files doesn't rename right now, so we'll just nuke. + return unless @old_filename && @old_filename != filename + + old_full_filename = File.join(base_path, @old_filename) + @@container.delete_object(old_full_filename) + + @old_filename = nil + true + end + + def save_to_storage + if save_attachment? + @object = @@container.create_object(full_filename) + @object.write((temp_path ? File.open(temp_path) : temp_data)) + end + + @old_filename = nil + true + end + end + end + end +end