require 'fileutils' require 'facet/inheritor' module Glue # A Web File. # # You can customize the path where the uploaded file will be # by defining a webfile_path class method *before* the property: # # class Icon # def self.webfile_path request, name # File.join(Uploads.public_root, request.user.name, 'icon.png') # end # # property :file, WebFile, :magick => { :small => '64x64', :medium => '96x96' } # end #-- # TODO: webfile_path customization sucks, should be improved! #++ class WebFile # The directory where uploaded files are stored. Typically # this is a symlink to another directory outside of the # webapp dir for easier updates. setting :upload_root, :default => 'upload', :doc => 'The directory where upload files are stored' # Modify the base class when this class is included as # property def self.included_as_property(base, names, options) if thumbnails = (options[:thumbnail] || options[:thumbnails] || options[:magick]) or self.name == 'WebImage' require 'glue/thumbnails' base.send :include, Thumbnails thumbnails = { :small => :thumbnails } if thumbnails.is_a?(String) end for name in names base.module_eval do # The 'web' path to the file (relative to the public # root directory. Uses the original property name # or the #{name}_path alias. property name.to_sym, String alias_method "#{name}_path".to_sym, name.to_sym # The file size. property "#{name}_size".to_sym, Fixnum # The mime type property "#{name}_mime_type".to_sym, String # Assignment callbacks. #-- # gmosx, FIXME: this is a hack!! better implementation # is needed (generalized property assigners). inheritor(:assign_callbacks, [], :merge) unless @assign_callbacks end if thumbnails for tname in thumbnails.keys base.module_eval do property "#{name}_#{tname}_thumbnail".to_sym, String end end end code = %{ def #{name}_real_path File.join(Nitro::Server.public_root, @#{name}) end def #{name}_from_request(request) param = request['#{name}'] } if base.respond_to? :webfile_path code << %{ path = #{base}.webfile_path(request, '#{name}') } else code << %{ path = File.join(WebFile.upload_root, param.original_filename) } end code << %{ @#{name} = WebFile.sanitize(path) @#{name}_size = param.size real_path = #{name}_real_path FileUtils.mkdir_p(File.dirname(real_path)) if param.path FileUtils.cp(param.path, real_path) else # gmosx FIXME: this is a hack!! param.rewind File.open(real_path, 'wb') { |f| f << param.read } end FileUtils.chmod(0777, real_path) } if thumbnails for tname, geostring in thumbnails code << %{ @#{name}_#{tname}_thumbnail = Thumbnails.generate_thumbnail(path, '#{tname}', '#{geostring}') } end end code << %{ end def delete_#{name} FileUtils.rm(#{name}_real_path) end assign_callbacks! << proc { |obj, values, options| obj.#{name}_from_request(values) } } base.module_eval(code) end end # Sanitize a filename. #-- # TODO: implement me! #++ def self.sanitize(filename) filename end end # An alias, implies thumbnailing. WebImage = WebFile end # * George Moschovitis # * Michael Fellinger