lib/attached/attachment.rb in attached-0.5.2 vs lib/attached/attachment.rb in attached-0.5.3

- old
+ new

@@ -5,14 +5,14 @@ require 'attached/processor' require 'attached/processor/error' module Attached - + class Attachment - - + + attr_reader :file attr_reader :name attr_reader :instance attr_reader :queue attr_reader :purge @@ -28,33 +28,33 @@ attr_reader :processor attr_reader :aliases attr_reader :alias attr_reader :storage attr_reader :host - - + + # A default set of options that can be extended to customize the path, storage or credentials. # # Usage: # # Attached::Attachment.options = { :storage => :fs, :path => ":name/:style/:identifier:extension" } - + def self.options @options ||= { :path => ":name/:style/:identifier:extension", :missing => ":name/:style/missing:extension", :default => :original, :medium => :local, :credentials => {}, } end - - + + # Initialize a new attachment by providing a name and the instance the attachment is associated with. # # Parameters: - # + # # * name - The name for the attachment such as 'avatar' or 'photo' # * instance - The instance the attachment is attached to # # Options: # @@ -62,27 +62,27 @@ # * :styles - A hash containing optional parameters including extension and identifier # * :credentials - A file, hash, or path used to authenticate with the specified storage medium # * :medium - A symbol or subclass of 'Attached::Storage::Base' to be used # * :processor - A symbol or subclass of 'Attached::Processor::Base' to be used # * :alias - A string representing a fully qualified host alias - # * :processors - An array of processors + # * :processors - An array of processors # * :aliases - An array of aliases - + def initialize(name, instance, options = {}) options = self.class.options.clone.merge(options) - + options[:styles] ||= {} options[:aliases] ||= [] options[:processors] ||= [] - + @name = name @instance = instance - + @queue = {} @purge = [] @errors = [] - + @path = options[:path] @missing = options[:missing] @styles = options[:styles] @default = options[:default] @strategy = options[:strategy] @@ -90,329 +90,329 @@ @credentials = options[:credentials] @processors = options[:processors] @processor = options[:processor] @aliases = options[:aliases] @alias = options[:alias] - + @aliases = self.aliases << self.alias if self.alias @processors = self.processors << self.processor if self.processor - + @storage = Attached::Storage.storage(self.medium, self.credentials) - + @host = self.storage.host end - - + + # Check if an attachment has been modified. # # Usage: # # @object.avatar.changed? - + def changed? instance.changed.include? "#{name}_identifier" end - - + + # Check if an attachment is present. # # Usage: # # @object.avatar.file? - + def file? not identifier.blank? end - - + + # Check if an attachment is present. # # Usage: # # @object.avatar.attached? - + def attached? not identifier.blank? end - - + + # Custom setter for specifying an attachment. - # + # # Usage: # # @object.avatar.file = File.open(...) - + def file=(file) @file = file @file = file.tempfile if file.respond_to?(:tempfile) end - - + + # Assign an attachment to a file. # # Usage: # # @object.avatar.assign(...) - + def assign(file, identifier = Identifier.generate) self.file = file - + if file extension ||= file.extension if file.respond_to? :extension extension ||= File.extname(file.original_filename) if file.respond_to? :original_filename extension ||= File.extname(file.path) if file.respond_to? :path - + size ||= file.size if file.respond_to? :size size ||= File.size(file.path) if file.respond_to? :path end - + @purge = [self.path, *self.styles.map { |style, options| self.path(style) }] if attached? - + self.size = file ? size : nil self.extension = file ? extension : nil self.identifier = file ? identifier : nil - + process if file end - - + + # Save an attachment. # # Usage: # # @object.avatar.save - - def save + + def save self.queue.each do |style, file| path = self.path(style) self.storage.save(file, path) if file and path end - + self.purge.each do |path| self.storage.destroy(path) end - + @purge = [] @queue = {} end - - + + # Destroy an attachment. # # Usage: # # @object.avatar.destroy - + def destroy if attached? self.storage.destroy(self.path) self.styles.each do |style, options| self.storage.destroy(self.path(style)) end end - + @purge = [] @queue = {} end - - + + # Acesss the URL for an attachment. # # Usage: # # @object.avatar.url # @object.avatar.url(:small) # @object.avatar.url(:large) - + def url(style = self.default) path = self.path(style) - + host = self.host host = self.aliases[path.hash % self.aliases.count] unless self.aliases.empty? - + return "#{host}#{path}" end - - - # Access the path for an attachment. + + + # Access the path for an attachment. # # Usage: # # @object.avatar.url # @object.avatar.url(:small) # @object.avatar.url(:large) - + def path(style = self.default) path = self.attached? ? @path.clone : @missing.clone - + path.gsub!(/:name/, name.to_s) path.gsub!(/:style/, style.to_s) path.gsub!(/:extension/, extension(style).to_s) path.gsub!(/:identifier/, identifier(style).to_s) return path end - - + + # Access the size for an attachment. # # Usage: # # @object.avatar.size - + def size return instance_get(:size) end - - + + # Access the status for an attachment. # # Usage: # # @object.avatar.status - + def status instance_get(:status) end - - - # Access the extension for an attachment. It will first check the styles + + + # Access the extension for an attachment. It will first check the styles # to see if one is specified before checking the instance. # # Usage: # # @object.avatar.extension - + def extension(style = nil) style and - self.styles and - self.styles[style] and - self.styles[style][:extension] or + self.styles and + self.styles[style] and + self.styles[style][:extension] or instance_get(:extension) end - - - # Access the identifier for an attachment. It will first check the styles + + + # Access the identifier for an attachment. It will first check the styles # to see if one is specified before checking the instance. # # Usage: # # @object.avatar.identifier - + def identifier(style = nil) style and - self.styles and - self.styles[style] and - self.styles[style][:identifier] or + self.styles and + self.styles[style] and + self.styles[style][:identifier] or instance_get(:identifier) end - - + + # Set the size for an attachment. # # Usage: # # @object.avatar.size = 1024 - + def size=(size) instance_set(:size, size) end - - + + # Set the status for an attachment. # # Usage: # # @object.avatar.status = 'processing' - + def status=(status) instance_set(:size, status) end - - - # Set the extension for an attachment. It will act independently of the + + + # Set the extension for an attachment. It will act independently of the # defined style. # # Usage: # # @object.avatar.extension = ".png" - + def extension=(extension) instance_set(:extension, extension) end - - - # Set the identifier for an attachment. It will act independently of the + + + # Set the identifier for an attachment. It will act independently of the # defined style. # # Usage: # # @object.avatar.identifier = "1234" - + def identifier=(identifier) instance_set(:identifier, identifier) end - - + + # Access the original file . - + def reprocess! self.file = self.storage.retrieve(self.path) - + process end - - + + private - - + + # Helper function for calling processors (will queue default). # # Usage: # # self.process - + def process self.queue[self.default] = self.file - + begin - + self.processors.each do |processor| processor = Attached::Processor.processor(processor) self.styles.each do |style, options| self.queue[style] = processor.process(self.queue[style] || self.file, options, self) end end - + rescue Attached::Processor::Error => error self.errors << error.message end end - - + + # Helper function for setting instance variables. - # + # # Usage: # # self.instance_set(size, 12345) - + def instance_set(attribute, value) setter = :"#{self.name}_#{attribute}=" self.instance.send(setter, value) if instance.respond_to?(setter) end - - + + # Helper function for getting instance variables. # # Usage: # # self.instance_get(size) - + def instance_get(attribute) getter = :"#{self.name}_#{attribute}" self.instance.send(getter) if instance.respond_to?(getter) end - + end - + end \ No newline at end of file