lib/milton/attachment.rb in citrusbyte-milton-0.1.8 vs lib/milton/attachment.rb in citrusbyte-milton-0.1.9

- old
+ new

@@ -3,16 +3,22 @@ module Citrusbyte module Milton module Attachment def self.included(base) + base.class_inheritable_accessor :milton_options + base.milton_options = {} base.extend Citrusbyte::Milton::Attachment::AttachmentMethods end module AttachmentMethods def has_attachment_methods(options={}) - raise "Milton requires a filename column on #{table_name} table" unless column_names.include?("filename") + begin + raise "Milton requires a filename column on #{class_name} table" unless column_names.include?("filename") + rescue ActiveRecord::StatementInvalid => i + # table doesn't exist yet, i.e. hasn't been migrated in... + end # character used to seperate a filename from its derivative options, this # character will be stripped from all incoming filenames and replaced by # replacement options[:separator] ||= '.' @@ -23,11 +29,11 @@ options[:file_system_path] ||= File.join(RAILS_ROOT, "public", table_name) # mode to set on stored files and created directories options[:chmod] ||= 0755 - AttachableFile.options = options + self.milton_options.merge!(options) validates_presence_of :filename before_destroy :destroy_attached_file @@ -41,11 +47,11 @@ # as well) # # TODO: change the filename on the underlying file system on save so as # not to orphan the file def filename=(name) - write_attribute :filename, AttachableFile.sanitize_filename(name) + write_attribute :filename, AttachableFile.sanitize_filename(name, self.milton_options) end # Simple helper, same as path except returns the directory from # .../public/ on, i.e. for showing images in your views. # @@ -85,27 +91,25 @@ # AttachableFile is what Milton uses to interface between your model and # the underlying file. Rather than just pushing a whole bunch of methods # into your model, you get a reference to an AttachableFile (or something # that extends AttachableFile). class AttachableFile - class_inheritable_accessor :options - class << self - # Sanitizes the given filename, removes pathnames and the special chars - # needed for options seperation for derivatives - def sanitize_filename(filename) - File.basename(filename, File.extname(filename)).gsub(/^.*(\\|\/)/, ''). - gsub(/[^\w]|#{Regexp.escape(options[:separator])}/, options[:replacement]). - strip + File.extname(filename) - end + # Sanitizes the given filename, removes pathnames and the special chars + # needed for options seperation for derivatives + def sanitize_filename(filename, options) + File.basename(filename, File.extname(filename)).gsub(/^.*(\\|\/)/, ''). + gsub(/[^\w]|#{Regexp.escape(options[:separator])}/, options[:replacement]). + strip + File.extname(filename) + end - # Creates the given directory and sets it to the mode given in - # options[:chmod] - def recreate_directory(directory) - FileUtils.mkdir_p(directory) - File.chmod(options[:chmod], directory) - end + # Creates the given directory and sets it to the mode given in + # options[:chmod] + def recreate_directory(directory, options) + FileUtils.mkdir_p(directory) + File.chmod(options[:chmod], directory) + end # Partitioner that takes an id, pads it up to 12 digits then splits # that into 4 folders deep, each 3 digits long. # # i.e. @@ -130,10 +134,15 @@ # decouple) def initialize(attachment, filename) @attachment = attachment @filename = filename end + + # Returns the milton options on the associated attachment. + def milton_options + self.attachment.class.milton_options + end # Returns the full path and filename to the file with the given options. # If no options are given then returns the path and filename to the # original file. def path(options={}) @@ -168,16 +177,16 @@ self.class.partition(self.attachment.id) end # The full path to the root of where files will be stored on disk. def root_path - self.class.options[:file_system_path] + milton_options[:file_system_path] end # Recreates the directory this file will be stored in. def recreate_directory - self.class.recreate_directory(dirname) unless File.exists?(dirname) + self.class.recreate_directory(dirname, milton_options) unless File.exists?(dirname) end # Removes the containing directory from the filesystem (and hence the # file and any derivatives) def destroy_file @@ -215,17 +224,10 @@ key, value = option.split('=') [ key.to_sym, value ] }).flatten] end - # Merges the given options to build a derviative filename and returns - # the resulting filename. - def filename_for(filename, options={}) - append = options.collect{ |k, v| "#{k}=#{v}" }.sort.join('_') - File.basename(filename, File.extname(filename)) + (append.blank? ? '' : "#{AttachableFile.options[:separator]}#{append}") + File.extname(filename) - end - # Given a filename (presumably with options embedded in it) parses out # the options and returns them as a hash. def extract_options_from(filename) File.basename(filename, File.extname(filename))[(filename.rindex(AttachableFile.options[:separator]) + 1)..-1] end @@ -245,10 +247,15 @@ @options = options end # The resulting filename of this Derivative with embedded options. def filename - self.class.filename_for(@file.path, options) + filename = @file.path + append = options.collect{ |k, v| "#{k}=#{v}" }.sort.join('_') + + File.basename(filename, File.extname(filename)) + + (append.blank? ? '' : "#{@file.milton_options[:separator]}#{append}") + + File.extname(filename) end # The full path and filename to this Derivative. def path File.join(@file.dirname, filename)