require 'ftools' module ScribdFu module AttachmentFu module ClassMethods # Adds validations to the current model to check that its attachment is # scribdable. def validates_as_scribd_document validates_presence_of :scribd_id, :scribd_access_key, :content_type validate :scribdable? end end module InstanceMethods def self.included(base) base.extend ClassMethods end # Checks whether the attachment is scribdable. This boils down to a check # to ensure that the contents of the attachment are of a content type that # scribd can understand. def scribdable? ScribdFu::CONTENT_TYPES.include?(content_type) end def scribd_id=(id) write_attribute :scribd_id, id.to_s.strip end def scribd_access_key=(key) write_attribute :scribd_access_key, key.to_s.strip end # Destroys the scribd document for this record. This is called # +before_destroy+, as set up by ScribdFu::ClassMethods#extended. # # Also available as destroy_scribd_document, which makes more sense in # terms of pluralization for external calls. def destroy_scribd_documents unless scribd_document.nil? if scribd_document.destroy logger.info "[Scribd_fu] #{Time.now.rfc2822}: Removing Object #{id} successful" else logger.info "[Scribd_fu] #{Time.now.rfc2822}: Removing Object #{id} failed!" end end end alias_method :destroy_scribd_document, :destroy_scribd_documents # Uploads the attachment to scribd for processing.. This is called # +before_validation+, as set up by ScribdFu::ClassMethods#extended. def upload_to_scribd if scribdable? and self.scribd_id.blank? with_file_path do |file_path| if resource = scribd_login.upload(:file => "#{file_path}", :access => access_level) logger.info "[Scribd_fu] #{Time.now.rfc2822}: Uploaded '#{file_path}' to Scribd" logger.info "[Scribd_fu] #{Time.now.rfc2822}: Object #{id} successfully uploaded for conversion to iPaper" self.scribd_id = resource.doc_id self.scribd_access_key = resource.access_key save else logger.info "[Scribd_fu] #{Time.now.rfc2822}: Object #{id} upload failed!" end end end end # Returns a URL for a thumbnail for this model's attachment. # # If Scribd does not provide a thumbnail URL, then Attachment_fu's # thumbnail is fallen back on by returning the value of # public_filename(:thumb). # # Sample use in a view: # <%= image_tag(@attachment .thumbnail_url, :alt => @attachment.name) %> def thumbnail_url (scribd_document && scribd_document.thumbnail_url) or public_filename(:thumb) end # Returns the actual image data of a thumbnail for this model's # attachment. # # If Scribd does not have a thumbnail for this file, then Attachment_fu's # thumbnanil is fallen back on by returning the file at # full_filename(:thumb). # # Sample use in a controller: # render :inline => @attachment.thumbnail_file, # :content_type => 'image/jpeg' def thumbnail_file path = (scribd_document && scribd_document.thumbnail_url) || full_filename(:thumb) open(path).read rescue Errno::ENOENT nil end # Yields the correct path to the file, either the local filename or the # S3 URL. # # This method creates a temporary file of the correct filename if # necessary, so as to be able to give scribd the right filename. The file # is destroyed when the passed block ends. def with_file_path(&block) # :yields: full_file_path # TODO We can probably do this using respond_to? if scribd_config['storage'].eql?('s3') yield public_filename elsif save_attachment? # file hasn't been saved, use the temp file temp_rename = File.join(Dir.tmpdir, filename) File.copy(temp_path, temp_rename) yield temp_rename else yield full_filename end ensure temp_rename && File.unlink(temp_rename) # always delete this end # Responds true if the conversion is complete -- note that this gives no # indication as to whether the conversion had an error or was succesful, # just that the conversion completed. # # Note that this method still returns false if the model does not refer to a # valid document. scribd_attributes_valid? should be used to determine the # validity of the document. def conversion_complete? scribd_document && scribd_document.conversion_status != 'PROCESSING' end # Responds true if the document has been converted. # # Note that this method still returns false if the model does not refer to a # valid document. scribd_attributes_valid? should be used to determine the # validity of the document. def conversion_successful? scribd_document && scribd_document.conversion_status =~ /^DISPLAYABLE|DONE$/ end # Responds true if there was a conversion error while converting # to iPaper. # # Note that this method still returns false if the model does not refer to a # valid document. scribd_attributes_valid? should be used to determine the # validity of the document. def conversion_error? scribd_document && scribd_document.conversion_status == 'ERROR' end # Responds the Scribd::Document associated with this model, or nil if it # does not exist. def scribd_document @scribd_document ||= scribd_login.find_document(scribd_id) rescue Scribd::ResponseError # at minimum, the document was not found nil end end end end