lib/imagery/model.rb in imagery-0.0.1 vs lib/imagery/model.rb in imagery-0.0.2
- old
+ new
@@ -1,59 +1,174 @@
module Imagery
class Model
UnknownSize = Class.new(StandardError)
+
+ @@directory = 'public/system'
+ @@default = { :original => ["1920x1200>"] }
+ # This is typically the database ID, you may also use something
+ # like a GUID for it, the sky's the limit.
attr :key
+
+ # Used as a grouping scheme, if you name this as `photos` for example,
+ # you will have public/system/photos as the path.
attr :namespace
+
+ # Returns a single key => value pair hash, defaulting to @@default.
attr :default
+
+ # Returns the directory used which defaults to public/system.
attr :directory
+
+ # Defaulting to :original, the value used here will be the default
+ # size used when calling Imagery::Model#url and Imagery::Model#file.
+ attr_accessor :default_size
- attr_writer :root, :sizes
+ # Allows you to define the root of your application, all other paths
+ # are determined relative to this.
+ attr_writer :root
+
+ # Allows you to define the different sizes you want as a hash of
+ # :style => [geometry] pairs.
+ attr_writer :sizes
- def initialize(model, key = model.id, namespace = model.class.name.split('::').last.downcase)
- @key = key.to_s
- @namespace = namespace
- @default = { :original => ["1920x1200>"] }
- @directory = 'public/system'
- @sizes = {}
+ # @param [#id] model any ruby object
+ # @param [#to_s] key typically the database ID of a model. But you may also
+ # use anything here just as long as its unique across the
+ # namespace.
+ # @param [String] namespace used as a grouping mechanism for your images.
+ def initialize(model, key = model.id, namespace = namespace_for(model.class))
+ @key = key.to_s
+ @namespace = namespace
+ @default = @@default
+ @directory = @@directory
+ @sizes = {}
+ @default_size = :original
end
+ # Returns all the sizes defined including the default size.
+ #
+ # @example
+ # Photo = Class.new(Struct.new(:id))
+ # i = Imagery::Model.new(Photo.new(1001))
+ # i.sizes == { :original => ["1920x1280"] }
+ # # => true
+ #
+ # i.sizes = { :thumb => ["48x48"] }
+ # i.sizes == { :thumb => ["48x48"], :original => ["1920x1280"] }
+ # # => true
+ #
+ # @return [Hash] size => [dimension] pairs.
def sizes
- @sizes.merge(@default)
+ @sizes.merge(default)
end
- def file(size = :original)
+ # Gives the absolute file for a specified size.
+ #
+ # @example
+ #
+ # Photo = Class.new(Struct.new(:id))
+ # i = Imagery.new(Photo.new(1001))
+ # i.root = '/tmp'
+ # i.file(:original) == '/tmp/public/system/photo/1001/original.png
+ # # => true
+ #
+ # i.file(:thumb)
+ # # raise Imagery::Model::UnknownSize
+ #
+ # i.sizes = { :thumb => ["100x100"] }
+ # i.file(:thumb) == '/tmp/public/system/photo/1001/thumb.png
+ # # => true
+ #
+ # @param [Symbol] size the size specific filename.
+ # @raise [UnknownSize] if the size is not found in
+ # Imagery::Model#sizes.
+ # @return [String] the absolute path of the size specific filename e.g.
+ # /u/apps/reddit/current/public/system/photo/1/thumb.png
+ # where photo is the namespace and 1 is the key.
+ def file(size = self.default_size)
raise UnknownSize, "#{ size } is not defined" unless sizes.has_key?(size)
root_path(directory, namespace, key, filename(size))
end
- def tmp
- root_path(directory, namespace, key, 'tmp')
- end
-
- def url(size = :original)
+ # Gives the absolute URI path for use in a web context.
+ #
+ # Photo = Class.new(Struct.new(:id))
+ # i = Imagery.new(Photo.new(1001))
+ # i.url(:original) == '/system/photo/1001/original.png
+ # # => true
+ #
+ # i.file(:thumb)
+ # # raise Imagery::Model::UnknownSize
+ #
+ # i.sizes = { :thumb => ["100x100"] }
+ # i.file(:thumb) == '/system/photo/1001/thumb.png
+ # # => true
+ #
+ # @param [Symbol] size the size specific url.
+ # @raise [UnknownSize] if the size is not found in
+ # Imagery::Model#sizes.
+ # @return [String] the absolute URI path of the size specific url e.g.
+ # /system/photo/1/thumb.png
+ # where photo is the namespace and 1 is the key.
+ def url(size = self.default_size)
file(size).split('public').last
end
+ # This module is basically here so that plugins like Imagery::S3
+ # can override #save and #delete and call super.
module Persistence
+ # Writes the data in `io` and resizes them according to the different
+ # geometry strings.
+ #
+ # @example
+ #
+ # Photo = Class.new(Struct.new(:id))
+ # i = Imagery.new(Photo.new(1001))
+ # i.root = '/tmp'
+ # i.size = { :thumb => ["48x48"] }
+ # i.save(File.open('/path/to/file.jpg'))
+ #
+ # File.exist?("/tmp/public/system/photo/1001/thumb.png")
+ # # => true
+ #
+ # File.exist?("/tmp/public/system/photo/1001/original.png")
+ # # => true
+ #
+ # @param [#read] io any object responding to read. Typically
+ # a Rack filehandle is passed here from a
+ # controller in rails or a Sinatra handler.
+ # You may also use File.open to provide a proper
+ # IO handle.
+ # @return [true] returns when all other file operations are done.
def save(io)
FileUtils.mkdir_p(File.dirname(tmp))
File.open(tmp, "wb") { |target| target.write(io.read) }
sizes.keys.each { |size| convert(size) }
FileUtils.rm(tmp)
return true
end
-
+
+ # Deletes all of the files related to this Imagery::Model instance.
+ # @return [true] when successfully deleted.
def delete
FileUtils.rm_rf File.dirname(file)
return true
end
end
include Persistence
private
+ def tmp
+ root_path(directory, namespace, key, 'tmp')
+ end
+
+ def namespace_for(klass)
+ klass.name.split('::').last.downcase
+ end
+
def filename(size)
"%s.png" % size
end
def convert(size, geometry = self.sizes[size][0], extent = self.sizes[size][1])