101 lines
2.9 KiB
Ruby
101 lines
2.9 KiB
Ruby
require 'mini_magick'
|
|
|
|
class Image < ActiveRecord::Base
|
|
attr_accessor :file
|
|
belongs_to :people
|
|
validates_presence_of :people_id
|
|
before_validation_on_create :set_people_id
|
|
before_create :validate_image_sanity
|
|
after_create :setup_directories
|
|
before_destroy :destroy_directories
|
|
has_many :tag_images, :dependent => :destroy
|
|
has_many :tagged_items, :through => :tag_images
|
|
|
|
##
|
|
# Builds the filename for this model for a particular version of the file.
|
|
#
|
|
def filename_for_version(ver = :screen)
|
|
if respond_to?(ver)
|
|
"community/#{id}/#{self.send(ver)}"
|
|
else
|
|
"/images/image-missing.png"
|
|
end
|
|
end
|
|
|
|
protected
|
|
|
|
##
|
|
# Determines the base directory for all files in this model.
|
|
#
|
|
def base_directory
|
|
"#{RAILS_ROOT}/public/images/community/#{id}"
|
|
end
|
|
|
|
##
|
|
# Sets the People marker for ownership on creation.
|
|
#
|
|
def set_people_id
|
|
self[:people_id] = ApplicationController.current_people_id rescue nil
|
|
self[:people_id] ||= People.penguincoder.id rescue nil
|
|
end
|
|
|
|
##
|
|
# Checks to make sure that the file exists and is an image.
|
|
#
|
|
def validate_image_sanity
|
|
if @file.nil? or @file.to_s.empty?
|
|
errors.add(:file, 'is not a file')
|
|
return false
|
|
end
|
|
errors.add(:file, 'is too big (3MB max)') if @file.size > 3 * 1048576
|
|
begin
|
|
@magick_image = MiniMagick::Image.from_blob(@file.read,
|
|
File.extname(@file.original_filename))
|
|
rescue
|
|
logger.debug("Caught an exception saving an image:")
|
|
logger.debug("* #{$!}")
|
|
errors.add(:file, 'is not an image')
|
|
end
|
|
return false if self.errors.size > 0
|
|
self.content_type = @file.content_type.chomp
|
|
true
|
|
end
|
|
|
|
##
|
|
# Makes the directories and writes the different versions for the uploaded
|
|
# files if applicable.
|
|
#
|
|
def setup_directories
|
|
File.umask(0022)
|
|
Dir.mkdir(base_directory) unless File.exist?(base_directory)
|
|
self.original = File.basename(@file.original_filename).gsub(/[^\w._-]/, '')
|
|
@magick_image.write("#{base_directory}/#{self.original}")
|
|
File.chmod(0644, "#{base_directory}/#{self.original}")
|
|
@magick_image.thumbnail("600x600>")
|
|
self.screen = "screen_#{self.original}"
|
|
@magick_image.write("#{base_directory}/#{self.screen}")
|
|
if @magick_image.output =~ / (\d+)x(\d+) /
|
|
self.screen_width = $1
|
|
self.screen_height = $2
|
|
end
|
|
File.chmod(0644, "#{base_directory}/#{self.screen}")
|
|
@magick_image.thumbnail("50x50>")
|
|
self.thumbnail = "thumbnail_#{self.original}"
|
|
@magick_image.write("#{base_directory}/#{self.thumbnail}")
|
|
File.chmod(0644, "#{base_directory}/#{self.thumbnail}")
|
|
self.save
|
|
end
|
|
|
|
##
|
|
# Removes the directories and files associated with this model on destroy.
|
|
#
|
|
def destroy_directories
|
|
return unless File.exists?(base_directory)
|
|
Dir.foreach(base_directory) do |file|
|
|
next if file =~ /^\.\.?$/
|
|
File.delete(base_directory + '/' + file)
|
|
end
|
|
Dir.delete(base_directory)
|
|
end
|
|
end
|