Permalink
Browse files

Extract some modules from Paperclip.rb

  • Loading branch information...
1 parent 5232b19 commit 03f777f88c6dc25949098eba2113ac6064bc637f @sikachu sikachu committed Mar 16, 2012
View
@@ -41,170 +41,40 @@
require 'paperclip/storage'
require 'paperclip/callbacks'
require 'paperclip/glue'
+require 'paperclip/errors'
require 'paperclip/missing_attachment_styles'
+require 'paperclip/validators'
+require 'paperclip/instance_methods'
+require 'paperclip/logger'
+require 'paperclip/helpers'
require 'paperclip/railtie'
require 'logger'
require 'cocaine'
# The base module that gets included in ActiveRecord::Base. See the
# documentation for Paperclip::ClassMethods for more useful information.
module Paperclip
-
- class << self
- # Provides configurability to Paperclip. The options available are:
- # * whiny: Will raise an error if Paperclip cannot process thumbnails of
- # an uploaded image. Defaults to true.
- # * log: Logs progress to the Rails log. Uses ActiveRecord's logger, so honors
- # log levels, etc. Defaults to true.
- # * command_path: Defines the path at which to find the command line
- # programs if they are not visible to Rails the system's search path. Defaults to
- # nil, which uses the first executable found in the user's search path.
- def options
- @options ||= {
- :whiny => true,
- :image_magick_path => nil,
- :command_path => nil,
- :log => true,
- :log_command => true,
- :swallow_stderr => true
- }
- end
-
- def configure
- yield(self) if block_given?
- end
-
- def interpolates key, &block
- Paperclip::Interpolations[key] = block
- end
-
- # The run method takes the name of a binary to run, the arguments to that binary
- # and some options:
- #
- # :command_path -> A $PATH-like variable that defines where to look for the binary
- # on the filesystem. Colon-separated, just like $PATH.
- #
- # :expected_outcodes -> An array of integers that defines the expected exit codes
- # of the binary. Defaults to [0].
- #
- # :log_command -> Log the command being run when set to true (defaults to false).
- # This will only log if logging in general is set to true as well.
- #
- # :swallow_stderr -> Set to true if you don't care what happens on STDERR.
- #
- def run(cmd, arguments = "", local_options = {})
- command_path = options[:command_path]
- Cocaine::CommandLine.path = ( Cocaine::CommandLine.path ? [Cocaine::CommandLine.path].flatten | [command_path] : command_path )
- local_options = local_options.merge(:logger => logger) if logging? && (options[:log_command] || local_options[:log_command])
- Cocaine::CommandLine.new(cmd, arguments, local_options).run
- end
-
- def processor(name) #:nodoc:
- @known_processors ||= {}
- if @known_processors[name.to_s]
- @known_processors[name.to_s]
- else
- name = name.to_s.camelize
- load_processor(name) unless Paperclip.const_defined?(name)
- processor = Paperclip.const_get(name)
- @known_processors[name.to_s] = processor
- end
- end
-
- def load_processor(name)
- if defined?(Rails.root) && Rails.root
- require File.expand_path(Rails.root.join("lib", "paperclip_processors", "#{name.underscore}.rb"))
- end
- end
-
- def clear_processors!
- @known_processors.try(:clear)
- end
-
- # You can add your own processor via the Paperclip configuration. Normally
- # Paperclip will load all processors from the
- # Rails.root/lib/paperclip_processors directory, but here you can add any
- # existing class using this mechanism.
- #
- # Paperclip.configure do |c|
- # c.register_processor :watermarker, WatermarkingProcessor.new
- # end
- def register_processor(name, processor)
- @known_processors ||= {}
- @known_processors[name.to_s] = processor
- end
-
- # Find all instances of the given Active Record model +klass+ with attachment +name+.
- # This method is used by the refresh rake tasks.
- def each_instance_with_attachment(klass, name)
- unscope_method = class_for(klass).respond_to?(:unscoped) ? :unscoped : :with_exclusive_scope
- class_for(klass).send(unscope_method) do
- class_for(klass).find_each(:conditions => "#{name}_file_name is not null") do |instance|
- yield(instance)
- end
- end
- end
-
- # Log a paperclip-specific line. This will log to STDOUT
- # by default. Set Paperclip.options[:log] to false to turn off.
- def log message
- logger.info("[paperclip] #{message}") if logging?
- end
-
- def logger #:nodoc:
- @logger ||= options[:logger] || Logger.new(STDOUT)
- end
-
- def logger=(logger)
- @logger = logger
- end
-
- def logging? #:nodoc:
- options[:log]
- end
-
- def class_for(class_name)
- # Ruby 1.9 introduces an inherit argument for Module#const_get and
- # #const_defined? and changes their default behavior.
- # https://github.com/rails/rails/blob/v3.0.9/activesupport/lib/active_support/inflector/methods.rb#L89
- if Module.method(:const_get).arity == 1
- class_name.split('::').inject(Object) do |klass, partial_class_name|
- klass.const_defined?(partial_class_name) ? klass.const_get(partial_class_name) : klass.const_missing(partial_class_name)
- end
- else
- class_name.split('::').inject(Object) do |klass, partial_class_name|
- klass.const_defined?(partial_class_name) ? klass.const_get(partial_class_name, false) : klass.const_missing(partial_class_name)
- end
- end
- end
-
- def check_for_url_clash(name,url,klass)
- @names_url ||= {}
- default_url = url || Attachment.default_options[:url]
- if @names_url[name] && @names_url[name][:url] == default_url && @names_url[name][:class] != klass && @names_url[name][:url] !~ /:class/
- log("Duplicate URL for #{name} with #{default_url}. This will clash with attachment defined in #{@names_url[name][:class]} class")
- end
- @names_url[name] = {:url => default_url, :class => klass}
- end
-
- def reset_duplicate_clash_check!
- @names_url = nil
- end
- end
-
- class PaperclipError < StandardError #:nodoc:
- end
-
- class StorageMethodNotFound < PaperclipError
- end
-
- class CommandNotFoundError < PaperclipError
- end
-
- class NotIdentifiedByImageMagickError < PaperclipError #:nodoc:
- end
-
- class InfiniteInterpolationError < PaperclipError #:nodoc:
+ extend Helpers
+ extend Logger
+ extend ProcessorHelpers
+
+ # Provides configurability to Paperclip. The options available are:
+ # * whiny: Will raise an error if Paperclip cannot process thumbnails of
+ # an uploaded image. Defaults to true.
+ # * log: Logs progress to the Rails log. Uses ActiveRecord's logger, so honors
+ # log levels, etc. Defaults to true.
+ # * command_path: Defines the path at which to find the command line
+ # programs if they are not visible to Rails the system's search path. Defaults to
+ # nil, which uses the first executable found in the user's search path.
+ def self.options
+ @options ||= {
+ :whiny => true,
+ :image_magick_path => nil,
+ :command_path => nil,
+ :log => true,
+ :log_command => true,
+ :swallow_stderr => true
+ }
end
module ClassMethods
@@ -287,7 +157,7 @@ module ClassMethods
# "/assets/avatars/default_#{gender}.png"
# end
# end
- def has_attached_file name, options = {}
+ def has_attached_file(name, options = {})
include InstanceMethods
if attachment_definitions.nil?
@@ -407,40 +277,4 @@ def attachment_definitions
self.attachment_definitions
end
end
-
- module InstanceMethods #:nodoc:
- def attachment_for name
- @_paperclip_attachments ||= {}
- @_paperclip_attachments[name] ||= Attachment.new(name, self, self.class.attachment_definitions[name])
- end
-
- def each_attachment
- self.class.attachment_definitions.each do |name, definition|
- yield(name, attachment_for(name))
- end
- end
-
- def save_attached_files
- Paperclip.log("Saving attachments.")
- each_attachment do |name, attachment|
- attachment.send(:save)
- end
- end
-
- def destroy_attached_files
- Paperclip.log("Deleting attachments.")
- each_attachment do |name, attachment|
- attachment.send(:flush_deletes)
- end
- end
-
- def prepare_for_destroy
- Paperclip.log("Scheduling attachments for deletion.")
- each_attachment do |name, attachment|
- attachment.send(:queue_existing_for_delete)
- end
- end
-
- end
-
end
@@ -365,7 +365,7 @@ def path_option
def ensure_required_accessors! #:nodoc:
%w(file_name).each do |field|
unless @instance.respond_to?("#{name}_#{field}") && @instance.respond_to?("#{name}_#{field}=")
- raise PaperclipError.new("#{@instance.class} model missing required attr_accessor for '#{name}_#{field}'")
+ raise Paperclip::Error.new("#{@instance.class} model missing required attr_accessor for '#{name}_#{field}'")
end
end
end
@@ -383,7 +383,7 @@ def initialize_storage #:nodoc:
begin
storage_module = Paperclip::Storage.const_get(storage_class_name)
rescue NameError
- raise StorageMethodNotFound, "Cannot load storage module '#{storage_class_name}'"
+ raise Errors::StorageMethodNotFound, "Cannot load storage module '#{storage_class_name}'"
end
self.extend(storage_module)
end
@@ -428,7 +428,7 @@ def post_process_style(name, style) #:nodoc:
@queued_for_write[name] = style.processors.inject(@queued_for_write[:original]) do |file, processor|
Paperclip.processor(processor).make(file, style.processor_options, self)
end
- rescue PaperclipError => e
+ rescue Paperclip::Error => e
log("An error was received while processing: #{e.inspect}")
(@errors[:processing] ||= []) << e.message if @options[:whiny]
end
View
@@ -0,0 +1,27 @@
+module Paperclip
+ # A base error class for Paperclip. Most of the error that will be thrown
+ # from Paperclip will inherits from this class.
+ class Error < StandardError
+ end
+
+ module Errors
+ # Will be thrown when a storage method is not found.
+ class StorageMethodNotFound < Paperclip::Error
+ end
+
+ # Will be thrown when a command or executable is not found.
+ class CommandNotFoundError < Paperclip::Error
+ end
+
+ # Will be thrown when ImageMagic cannot determine the uploaded file's
+ # metadata, usually this would mean the file is not an image.
+ class NotIdentifiedByImageMagickError < Paperclip::Error
+ end
+
+ # Will be thrown if the interpolation is creating an infinite loop. If you
+ # are creating an interpolator which might cause an infinite loop, you
+ # should be throwing this error upon the infinite loop as well.
+ class InfiniteInterpolationError < Paperclip::Error
+ end
+ end
+end
@@ -17,16 +17,16 @@ def initialize width = nil, height = nil, modifier = nil
# a Tempfile object, which would be eligible for file deletion when no longer referenced.
def self.from_file file
file_path = file.respond_to?(:path) ? file.path : file
- raise(Paperclip::NotIdentifiedByImageMagickError.new("Cannot find the geometry of a file with a blank name")) if file_path.blank?
+ raise(Errors::NotIdentifiedByImageMagickError.new("Cannot find the geometry of a file with a blank name")) if file_path.blank?
geometry = begin
Paperclip.run("identify", "-format %wx%h :file", :file => "#{file_path}[0]")
rescue Cocaine::ExitStatusError
""
rescue Cocaine::CommandNotFoundError => e
- raise Paperclip::CommandNotFoundError.new("Could not run the `identify` command. Please install ImageMagick.")
+ raise Errors::CommandNotFoundError.new("Could not run the `identify` command. Please install ImageMagick.")
end
parse(geometry) ||
- raise(NotIdentifiedByImageMagickError.new("#{file_path} is not recognized by the 'identify' command."))
+ raise(Errors::NotIdentifiedByImageMagickError.new("#{file_path} is not recognized by the 'identify' command."))
end
# Parses a "WxH" formatted string, where W is the width and H is the height.
View
@@ -0,0 +1,71 @@
+module Paperclip
+ module Helpers
+ def configure
+ yield(self) if block_given?
+ end
+
+ def interpolates key, &block
+ Paperclip::Interpolations[key] = block
+ end
+
+ # The run method takes the name of a binary to run, the arguments to that binary
+ # and some options:
+ #
+ # :command_path -> A $PATH-like variable that defines where to look for the binary
+ # on the filesystem. Colon-separated, just like $PATH.
+ #
+ # :expected_outcodes -> An array of integers that defines the expected exit codes
+ # of the binary. Defaults to [0].
+ #
+ # :log_command -> Log the command being run when set to true (defaults to false).
+ # This will only log if logging in general is set to true as well.
+ #
+ # :swallow_stderr -> Set to true if you don't care what happens on STDERR.
+ #
+ def run(cmd, arguments = "", local_options = {})
+ command_path = options[:command_path]
+ Cocaine::CommandLine.path = ( Cocaine::CommandLine.path ? [Cocaine::CommandLine.path].flatten | [command_path] : command_path )
+ local_options = local_options.merge(:logger => logger) if logging? && (options[:log_command] || local_options[:log_command])
+ Cocaine::CommandLine.new(cmd, arguments, local_options).run
+ end
+
+ # Find all instances of the given Active Record model +klass+ with attachment +name+.
+ # This method is used by the refresh rake tasks.
+ def each_instance_with_attachment(klass, name)
+ unscope_method = class_for(klass).respond_to?(:unscoped) ? :unscoped : :with_exclusive_scope
+ class_for(klass).send(unscope_method) do
+ class_for(klass).find_each(:conditions => "#{name}_file_name is not null") do |instance|
+ yield(instance)
+ end
+ end
+ end
+
+ def class_for(class_name)
+ # Ruby 1.9 introduces an inherit argument for Module#const_get and
+ # #const_defined? and changes their default behavior.
+ # https://github.com/rails/rails/blob/v3.0.9/activesupport/lib/active_support/inflector/methods.rb#L89
+ if Module.method(:const_get).arity == 1
+ class_name.split('::').inject(Object) do |klass, partial_class_name|
+ klass.const_defined?(partial_class_name) ? klass.const_get(partial_class_name) : klass.const_missing(partial_class_name)
+ end
+ else
+ class_name.split('::').inject(Object) do |klass, partial_class_name|
+ klass.const_defined?(partial_class_name) ? klass.const_get(partial_class_name, false) : klass.const_missing(partial_class_name)
+ end
+ end
+ end
+
+ def check_for_url_clash(name,url,klass)
+ @names_url ||= {}
+ default_url = url || Attachment.default_options[:url]
+ if @names_url[name] && @names_url[name][:url] == default_url && @names_url[name][:class] != klass && @names_url[name][:url] !~ /:class/
+ log("Duplicate URL for #{name} with #{default_url}. This will clash with attachment defined in #{@names_url[name][:class]} class")
+ end
+ @names_url[name] = {:url => default_url, :class => klass}
+ end
+
+ def reset_duplicate_clash_check!
+ @names_url = nil
+ end
+ end
+end
Oops, something went wrong.

0 comments on commit 03f777f

Please sign in to comment.