require 'fileutils'
module PlanetArgon # :nodoc:
module AssetField # :nodoc:
def self.included mod # :nodoc:
mod.extend ClassMethods
end
# Adds asset management capabilities to your model.
# Usage example
#
#
# class Page
# asset_field :asset,
# :directory => "#{RAILS_ROOT}/public/assets/images",
# :extensions => %w( .swf .qt ),
# :filename => :permalink
# end
#
#
# This defines the following attrbitues:
# * [R,W] asset_tempfile
#
# and the following instance methods:
# * Page#asset_file_on_disk Full pathname of the file on disk.
# * Page#asset_exist? Does the file actually exist on disk?
# * Page#write_asset_file Write the file to the path generated from the asset field's
# directory option and the method referenced by the filename option.
# * Page#destroy_asset_file Destroy the asset file.
module ClassMethods
# Configuration options are:
# * :directory Directory to save this field's assets in. Defaults to
# "#{RAILS_ROOT}/public/assets".
# * :filename A symbol referencing the name of a method returning a string returning a
# filename (minus the file's extension). It is of note that this could simply
# be a reference to another attribute.
# * :extensions An array of allowed file extensions. Omitting this option allows all file
# extensions.
def asset_field attr, options = {}
uploaded_filename_method = "#{attr}_uploaded_filename"
tempfile_method = "#{attr}_tempfile"
write_method = "write_#{attr}_file"
destroy_method = "destroy_#{attr}_file"
file_on_disk_method = "#{attr}_file_on_disk"
path_method = "#{attr}_path"
exist_method = "#{attr}_exist?"
directory_method = "#{attr}_directory"
options[:directory] ||= "#{RAILS_ROOT}/public/assets"
options[:filename]
attr_accessor tempfile_method
before_save write_method
before_destroy destroy_method
define_method uploaded_filename_method do
self.send(tempfile_method).original_filename if self.send(tempfile_method).kind_of?(Tempfile)
end
define_method directory_method do
@dir ||= case options[:directory]
when Proc
instance_eval &options[:directory]
when Symbol
self.send options[:directory]
when String
options[:directory]
end
end
define_method file_on_disk_method do
File.join self.send(directory_method), self.send(attr)
end
alias_method path_method, file_on_disk_method
define_method exist_method do
File.exist?(self.send(file_on_disk_method)) if self.send(attr)
end
unless options[:extensions].blank?
valid_extensions = options[:extensions].map{ |e| e.gsub '.', '\.' }.join('|')
validates_format_of uploaded_filename_method,
:with => /.*(#{valid_extensions})$/,
:allow_nil => true,
:message => 'file format is disallowed'
end
define_method write_method do
if self.send(tempfile_method) && !self.send(tempfile_method).kind_of?(String)
FileUtils.mkdir_p self.send(directory_method)
ext = File.extname self.send(tempfile_method).original_filename
self.send destroy_method if self.send exist_method
self.send "#{attr}=", self.send(options[:filename]) + ext
File.open self.send(file_on_disk_method), 'w' do |f|
f.write self.send(tempfile_method).read
end
self.send(tempfile_method).rewind
raise 'Error saving file' unless self.send(exist_method)
end
end
define_method destroy_method do
File.delete self.send(file_on_disk_method) if self.send exist_method
end
end
end
end
end