This repository has been archived on 2020-05-27. You can view files and clone it, but cannot push or open issues/pull-requests.
tuxbliki/app/models/photo.rb

111 lines
2.9 KiB
Ruby

class Photo < ActiveRecord::Base
attr_accessor :file
validates_presence_of :author_id, :album_id
belongs_to :album
belongs_to :author
has_many :photo_tags, :dependent => :destroy
has_many :tags, :through => :photo_tags
before_validation_on_create :set_author_id
before_create :validate_image_sanity
after_create :create_directories
before_destroy :destroy_directories
attr_protected :author_id
##
# Determines the base directory for all files in this model.
#
def base_directory
"#{Merb.root}/public/photos/#{id}"
end
##
# Checks to see if the file is found on the filesystem.
#
def exist?
File.exist?(self.pathname)
end
##
# Returns the full path to the file on the filesystem.
#
def pathname
"#{self.base_directory}/#{self.filename}"
end
def self.popular_tags(limit = nil)
query = "SELECT tags.id, tags.name, count(*) AS count FROM photo_tags, tags, photos WHERE tags.id = tag_id AND photo_tags.photo_id = photos.id GROUP BY tags.id, tags.name ORDER BY tags.name ASC"
query << " LIMIT #{limit}" unless limit.nil?
Tag.find_by_sql(query)
end
protected
##
# Sets the Author marker for ownership on creation.
#
def set_author_id
self.author_id ||= Application.current_author_id
end
##
# Checks to make sure that the file exists and is an image.
#
def validate_image_sanity
if self.file[:tempfile].nil?
self.errors.add(:file, 'File is not a file')
end
if self.file[:content_type] !~ /image\/\w+/
self.errors.add(:file, 'File is not a supported type')
end
if self.file[:size] > 3 * 1048576
self.errors.add(:file, 'File is too big (3MB max)')
end
return false unless self.errors.empty?
begin
@fstr = self.file[:tempfile].read
iary = Magick::Image.from_blob(@fstr)
self.filename = File.basename(self.file[:filename]).gsub(/[^\w._-]/, '')
if iary.first.to_s =~ / (\d+)x(\d+) /
self.width = $1
self.height = $2
end
rescue
$stderr.puts("Caught an exception saving an image:")
$stderr.puts("* #{$!}")
self.errors.add(:file, 'File could not be read as an image')
return false
end
self.content_type = self.file[:content_type]
true
end
##
# Makes the directories and writes the file to disk.
#
def create_directories
File.umask(0022)
Dir.mkdir(base_directory) unless File.exist?(base_directory)
File.open("#{base_directory}/#{self.filename}", "w") do |f|
f.puts(@fstr)
end
File.chmod(0644, "#{base_directory}/#{self.filename}")
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