mirror of
https://github.com/kemko/paperclip.git
synced 2026-01-06 02:15:41 +03:00
Merge pull request #10 from insales/cleanup
Remove old code, DRY, fixes
This commit is contained in:
@@ -42,12 +42,21 @@ require 'paperclip/matchers'
|
||||
require 'paperclip/callback_compatability'
|
||||
require 'paperclip/railtie' if defined?(Rails)
|
||||
|
||||
require 'active_support/concern'
|
||||
require 'active_support/core_ext/class/attribute'
|
||||
|
||||
# The base module that gets included in ActiveRecord::Base. See the
|
||||
# documentation for Paperclip::ClassMethods for more useful information.
|
||||
module Paperclip
|
||||
|
||||
VERSION = "2.2.9.2"
|
||||
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
included do
|
||||
class_attribute :attachment_definitions
|
||||
Paperclip::CallbackCompatability.install_to(self)
|
||||
end
|
||||
|
||||
class << self
|
||||
# Provides configurability to Paperclip. There are a number of options available, such as:
|
||||
# * whiny: Will raise an error if Paperclip cannot process thumbnails of
|
||||
@@ -109,17 +118,6 @@ module Paperclip
|
||||
File.exist?("/dev/null") ? "/dev/null" : "NUL"
|
||||
end
|
||||
|
||||
def included base #:nodoc:
|
||||
base.extend ClassMethods
|
||||
base.class_attribute :attachment_definitions
|
||||
|
||||
if base.respond_to?(:set_callback)
|
||||
base.send :include, Paperclip::CallbackCompatability::Rails3
|
||||
else
|
||||
base.send :include, Paperclip::CallbackCompatability::Rails21
|
||||
end
|
||||
end
|
||||
|
||||
def processor name #:nodoc:
|
||||
name = name.to_s.camelize
|
||||
processor = Paperclip.const_get(name)
|
||||
@@ -217,11 +215,7 @@ module Paperclip
|
||||
def has_attached_file name, options = {}
|
||||
include InstanceMethods
|
||||
|
||||
if attachment_definitions.nil?
|
||||
self.attachment_definitions = {}
|
||||
else
|
||||
self.attachment_definitions = self.attachment_definitions.dup
|
||||
end
|
||||
self.attachment_definitions = self.attachment_definitions&.dup || {}
|
||||
attachment_definitions[name] = {:validations => []}.merge(options)
|
||||
|
||||
after_save :save_attached_files
|
||||
@@ -258,16 +252,13 @@ module Paperclip
|
||||
# * +if+: A lambda or name of a method on the instance. Validation will only
|
||||
# be run is this lambda or method returns true.
|
||||
# * +unless+: Same as +if+ but validates if lambda or method returns false.
|
||||
def validates_attachment_size name, options = {}
|
||||
def validates_attachment_size(name, **options)
|
||||
min = options[:greater_than] || (options[:in] && options[:in].first) || 0
|
||||
max = options[:less_than] || (options[:in] && options[:in].last) || (1.0/0)
|
||||
range = (min..max)
|
||||
message = options[:message] || "file size must be between :min and :max bytes."
|
||||
|
||||
attachment_definitions[name][:validations] << [:size, {:range => range,
|
||||
:message => message,
|
||||
:if => options[:if],
|
||||
:unless => options[:unless]}]
|
||||
_add_attachment_validation(name, :size, options,
|
||||
message: "file size must be between :min and :max bytes.",
|
||||
range: (min..max)
|
||||
)
|
||||
end
|
||||
|
||||
# Places ActiveRecord-style validations on the presence of a file.
|
||||
@@ -275,12 +266,8 @@ module Paperclip
|
||||
# * +if+: A lambda or name of a method on the instance. Validation will only
|
||||
# be run is this lambda or method returns true.
|
||||
# * +unless+: Same as +if+ but validates if lambda or method returns false.
|
||||
def validates_attachment_presence name, options = {}
|
||||
message = options[:message] || :blank
|
||||
|
||||
attachment_definitions[name][:validations] << [:presence, {:message => message,
|
||||
:if => options[:if],
|
||||
:unless => options[:unless]}]
|
||||
def validates_attachment_presence(name, **options)
|
||||
_add_attachment_validation(name, :presence, options, message: :blank)
|
||||
end
|
||||
|
||||
# Places ActiveRecord-style validations on the content type of the file
|
||||
@@ -299,15 +286,16 @@ module Paperclip
|
||||
# NOTE: If you do not specify an [attachment]_content_type field on your
|
||||
# model, content_type validation will work _ONLY upon assignment_ and
|
||||
# re-validation after the instance has been reloaded will always succeed.
|
||||
def validates_attachment_content_type name, options = {}
|
||||
attachment_definitions[name][:validations] << [:content_type, {:content_type => options[:content_type],
|
||||
:message => options[:message],
|
||||
:if => options[:if],
|
||||
:unless => options[:unless]}]
|
||||
def validates_attachment_content_type(name, content_type:, **options)
|
||||
_add_attachment_validation(name, :content_type, options, content_type: content_type)
|
||||
end
|
||||
|
||||
def attachment_definitions
|
||||
self.attachment_definitions
|
||||
def _add_attachment_validation(name, type, default_options, options)
|
||||
attachment_definitions[name][:validations] << [
|
||||
type,
|
||||
**options,
|
||||
**default_options.slice(:message, :if, :unless)
|
||||
]
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
require 'fastimage'
|
||||
|
||||
require 'paperclip/styles_parser'
|
||||
|
||||
module Paperclip
|
||||
# The Attachment class manages the files for a given attachment. It saves
|
||||
# when the model saves, deletes when the model is destroyed, and processes
|
||||
@@ -14,13 +16,11 @@ module Paperclip
|
||||
@default_options ||= {
|
||||
:url => "/system/:attachment/:id/:style/:filename",
|
||||
:path => ":rails_root/public:url",
|
||||
:style_order => [],
|
||||
:styles => {},
|
||||
:default_url => "/:attachment/:style/missing.png",
|
||||
:default_style => :original,
|
||||
:validations => [],
|
||||
:storage => :filesystem,
|
||||
# :whiny => Paperclip.options[:whiny] || Paperclip.options[:whiny_thumbnails],
|
||||
:whiny => true,
|
||||
:restricted_characters => /[^\w\p{Word}\d\.\-]|(^\.{0,2}$)+/,
|
||||
:filename_sanitizer => nil
|
||||
@@ -48,8 +48,7 @@ module Paperclip
|
||||
attachment_class_cache[storage].new(name, instance, options)
|
||||
end
|
||||
|
||||
attr_reader :name, :instance, :style_order, :styles, :default_style,
|
||||
:convert_options, :queued_for_write, :options
|
||||
attr_reader :name, :instance, :styles, :default_style, :queued_for_write, :options
|
||||
|
||||
attr_accessor :post_processing
|
||||
|
||||
@@ -63,20 +62,13 @@ module Paperclip
|
||||
options = Attachment.default_options.merge(options)
|
||||
|
||||
@url = options[:url]
|
||||
@url = @url.call(self) if @url.is_a?(Proc)
|
||||
@path = options[:path]
|
||||
@path = @path.call(self) if @path.is_a?(Proc)
|
||||
@style_order = options[:style_order]
|
||||
@style_order = @style_order.call(self) if @style_order.is_a?(Proc)
|
||||
@styles = options[:styles]
|
||||
@styles = @styles.call(self) if @styles.is_a?(Proc)
|
||||
@styles = StylesParser.new(options).styles
|
||||
@default_url = options[:default_url]
|
||||
@validations = options[:validations]
|
||||
@default_style = options[:default_style]
|
||||
@storage = options[:storage]
|
||||
@whiny = options[:whiny_thumbnails] || options[:whiny]
|
||||
@convert_options = options[:convert_options] || {}
|
||||
@processors = options[:processors] || [:thumbnail]
|
||||
@options = options
|
||||
@queued_for_delete = []
|
||||
@queued_for_write = {}
|
||||
@@ -86,8 +78,6 @@ module Paperclip
|
||||
|
||||
@post_processing = true
|
||||
@processing_url = options[:processing_url] || @default_url
|
||||
|
||||
normalize_style_definition
|
||||
end
|
||||
|
||||
# What gets called when you call instance.attachment = File. It clears
|
||||
@@ -159,10 +149,6 @@ module Paperclip
|
||||
!sizes || (sizes[0] <= MAX_IMAGE_RESOLUTION && sizes[1] <= MAX_IMAGE_RESOLUTION)
|
||||
end
|
||||
|
||||
def most_appropriate_url
|
||||
# stub for delayed_paperclip
|
||||
end
|
||||
|
||||
# Returns the public URL of the attachment, with a given style. Note that
|
||||
# this does not necessarily need to point to a file that your web server
|
||||
# can access and can point to an action in your app, if you need fine
|
||||
@@ -274,18 +260,6 @@ module Paperclip
|
||||
time && time.to_i
|
||||
end
|
||||
|
||||
# Paths and URLs can have a number of variables interpolated into them
|
||||
# to vary the storage location based on name, id, style, class, etc.
|
||||
# This method is a deprecated access into supplying and retrieving these
|
||||
# interpolations. Future access should use either Paperclip.interpolates
|
||||
# or extend the Paperclip::Interpolations module directly.
|
||||
def self.interpolations
|
||||
warn('[DEPRECATION] Paperclip::Attachment.interpolations is deprecated ' +
|
||||
'and will be removed from future versions. ' +
|
||||
'Use Paperclip.interpolates instead')
|
||||
Paperclip::Interpolations
|
||||
end
|
||||
|
||||
def sanitize_filename(file_name)
|
||||
file_name = file_name.strip
|
||||
file_name.gsub!(@options[:restricted_characters], '_') if @options[:restricted_characters]
|
||||
@@ -415,48 +389,9 @@ module Paperclip
|
||||
end
|
||||
end
|
||||
|
||||
def normalize_style_definition #:nodoc:
|
||||
styles.each do |name, args|
|
||||
unless args.is_a? Hash
|
||||
dimensions, format = [args, nil].flatten[0..1]
|
||||
format = nil if format.blank?
|
||||
@styles[name] = {
|
||||
:processors => @processors,
|
||||
:geometry => dimensions,
|
||||
:format => format,
|
||||
:whiny => @whiny,
|
||||
:convert_options => extra_options_for(name)
|
||||
}
|
||||
else
|
||||
@styles[name] = {
|
||||
:processors => @processors,
|
||||
:whiny => @whiny,
|
||||
:convert_options => extra_options_for(name)
|
||||
}.merge(@styles[name])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def solidify_style_definitions #:nodoc:
|
||||
@styles.each do |name, args|
|
||||
@styles[name][:geometry] = @styles[name][:geometry].call(instance) if @styles[name][:geometry].respond_to?(:call)
|
||||
@styles[name][:processors] = @styles[name][:processors].call(instance) if @styles[name][:processors].respond_to?(:call)
|
||||
end
|
||||
end
|
||||
|
||||
def extra_options_for(style) #:nodoc:
|
||||
all_options = convert_options[:all]
|
||||
all_options = all_options.call(instance) if all_options.respond_to?(:call)
|
||||
style_options = convert_options[style]
|
||||
style_options = style_options.call(instance) if style_options.respond_to?(:call)
|
||||
|
||||
[ style_options, all_options ].compact.join(" ")
|
||||
end
|
||||
|
||||
def post_process #:nodoc:
|
||||
return unless content_type.match(/image/)
|
||||
return if @queued_for_write[:original].nil?
|
||||
solidify_style_definitions
|
||||
|
||||
instance.run_paperclip_callbacks(:post_process) do
|
||||
instance.run_paperclip_callbacks(:"#{name}_post_process") do
|
||||
@@ -466,8 +401,7 @@ module Paperclip
|
||||
end
|
||||
|
||||
def post_process_styles #:nodoc:
|
||||
styles_in_order = @style_order.empty? ? @styles : @styles.sort_by{|s| @style_order.index(s.first)}
|
||||
styles_in_order.each do |name, args|
|
||||
styles.each do |name, args|
|
||||
begin
|
||||
raise RuntimeError.new("Style #{name} has no processors defined.") if args[:processors].blank?
|
||||
@queued_for_write[name] = args[:processors].inject(@queued_for_write[:original]) do |file, processor|
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
module Paperclip
|
||||
module CallbackCompatability
|
||||
module Rails21
|
||||
def self.included(base)
|
||||
base.extend(Defining)
|
||||
base.send(:include, Running)
|
||||
end
|
||||
module_function
|
||||
|
||||
def install_to(base)
|
||||
mod = base.respond_to?(:set_callback) ? Rails3 : Rails21
|
||||
base.extend(mod::Defining)
|
||||
base.send(:include, mod::Running)
|
||||
end
|
||||
|
||||
module Rails21
|
||||
module Defining
|
||||
def define_paperclip_callbacks(*args)
|
||||
args.each do |callback|
|
||||
@@ -28,29 +31,24 @@ module Paperclip
|
||||
end
|
||||
|
||||
module Rails3
|
||||
def self.included(base)
|
||||
base.extend(Defining)
|
||||
base.send(:include, Running)
|
||||
end
|
||||
|
||||
module Defining
|
||||
TERMINATOR =
|
||||
if Gem::Version.new(ActiveRecord::VERSION::STRING) >= Gem::Version.new('4.1')
|
||||
->(target, result) { result == false }
|
||||
else
|
||||
'result == false'
|
||||
end
|
||||
|
||||
def define_paperclip_callbacks(*callbacks)
|
||||
terminator =
|
||||
if Gem::Version.new(ActiveRecord::VERSION::STRING) >= Gem::Version.new('4.1')
|
||||
->(target, result) { result == false }
|
||||
else
|
||||
'result == false'
|
||||
define_callbacks *[callbacks, {terminator: TERMINATOR}].flatten
|
||||
callbacks.map(&:to_sym).each do |callback|
|
||||
define_singleton_method "before_#{callback}" do |*args, &blk|
|
||||
set_callback(callback, :before, *args, &blk)
|
||||
end
|
||||
|
||||
define_singleton_method "after_#{callback}" do |*args, &blk|
|
||||
set_callback(callback, :after, *args, &blk)
|
||||
end
|
||||
define_callbacks *[callbacks, {terminator: terminator}].flatten
|
||||
callbacks.each do |callback|
|
||||
eval <<-end_callbacks
|
||||
def before_#{callback}(*args, &blk)
|
||||
set_callback(:#{callback}, :before, *args, &blk)
|
||||
end
|
||||
def after_#{callback}(*args, &blk)
|
||||
set_callback(:#{callback}, :after, *args, &blk)
|
||||
end
|
||||
end_callbacks
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -60,9 +58,7 @@ module Paperclip
|
||||
run_callbacks(callback, &block)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -14,9 +14,8 @@ module Paperclip
|
||||
end
|
||||
|
||||
def parse_credentials creds
|
||||
return @parsed_credentials if @parsed_credentials
|
||||
creds = find_credentials(creds).stringify_keys
|
||||
@parsed_credentials ||= (creds[Rails.env] || creds).symbolize_keys
|
||||
(creds[Rails.env] || creds).symbolize_keys
|
||||
end
|
||||
|
||||
def find_credentials creds
|
||||
@@ -33,12 +32,6 @@ module Paperclip
|
||||
end
|
||||
end
|
||||
|
||||
class WriteToS3Job < Struct.new(:class_name, :name, :id)
|
||||
def perform
|
||||
WriteToS3Worker.new.perform(class_name, name, id)
|
||||
end
|
||||
end
|
||||
|
||||
class UploadWorker
|
||||
include ::Sidekiq::Worker
|
||||
sidekiq_options queue: :paperclip
|
||||
@@ -81,10 +74,6 @@ module Paperclip
|
||||
|
||||
@s3_credentials = Delayeds3.parse_credentials(@options[:s3_credentials])
|
||||
@bucket = @options[:bucket] || @s3_credentials[:bucket]
|
||||
@bucket = @bucket.call(self) if @bucket.is_a?(Proc)
|
||||
@s3_permissions = @options[:s3_permissions] || 'public-read'
|
||||
@s3_protocol = @options[:s3_protocol] || (@s3_permissions == 'public-read' ? 'http' : 'https')
|
||||
@s3_host_alias = @options[:s3_host_alias]
|
||||
|
||||
@fog_provider = @options[:fog_provider]
|
||||
@fog_directory = @options[:fog_directory]
|
||||
@@ -141,10 +130,6 @@ module Paperclip
|
||||
@bucket
|
||||
end
|
||||
|
||||
def s3_host_alias
|
||||
@s3_host_alias
|
||||
end
|
||||
|
||||
def synced_to_s3_field
|
||||
@synced_to_s3_field ||= "#{name}_synced_to_s3".freeze
|
||||
end
|
||||
@@ -166,10 +151,6 @@ module Paperclip
|
||||
|
||||
alias_method :to_io, :to_file
|
||||
|
||||
def s3_protocol
|
||||
@s3_protocol
|
||||
end
|
||||
|
||||
def exists?(style = default_style)
|
||||
File.exist?(filesystem_path(style))
|
||||
end
|
||||
@@ -181,7 +162,8 @@ module Paperclip
|
||||
def filesystem_paths
|
||||
h = {}
|
||||
[:original, *@styles.keys].uniq.map do |style|
|
||||
h[style] = filesystem_path(style) if File.exist?(filesystem_path(style))
|
||||
path = filesystem_path(style)
|
||||
h[style] = path if File.exist?(path)
|
||||
end
|
||||
h
|
||||
end
|
||||
@@ -237,8 +219,9 @@ module Paperclip
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def flush_writes #:nodoc:
|
||||
return if @queued_for_write.empty?
|
||||
|
||||
@queued_for_write.each do |style, file|
|
||||
file.close
|
||||
FileUtils.mkdir_p(File.dirname(filesystem_path(style)))
|
||||
@@ -247,7 +230,7 @@ module Paperclip
|
||||
FileUtils.chmod(0644, filesystem_path(style))
|
||||
end
|
||||
|
||||
unless @queued_for_write.empty? || (delay_processing? && dirty?)
|
||||
unless delay_processing? && dirty?
|
||||
instance.update_column(synced_to_s3_field, false) if instance_read(:synced_to_s3)
|
||||
if instance.respond_to?(synced_to_fog_field) && instance_read(:synced_to_fog)
|
||||
instance.update_column(synced_to_fog_field, false)
|
||||
@@ -285,10 +268,9 @@ module Paperclip
|
||||
def flush_deletes #:nodoc:
|
||||
# если мы картинку заливали в облака, значит мы скорее всего ее уже удалили
|
||||
# и можно не нагружать хранилище проверками
|
||||
if !instance.is_a?(AccountFile) && instance_read(:synced_to_fog) &&
|
||||
instance_read(:synced_to_s3)
|
||||
@queued_for_delete = []
|
||||
return
|
||||
if instance_read(:synced_to_fog) && instance_read(:synced_to_s3)
|
||||
@queued_for_delete = []
|
||||
return
|
||||
end
|
||||
|
||||
@queued_for_delete.each do |path|
|
||||
@@ -299,7 +281,6 @@ module Paperclip
|
||||
end
|
||||
|
||||
def delete_local_files!
|
||||
return if instance.is_a?(AccountFile)
|
||||
instance.reload
|
||||
if instance_read(:synced_to_fog) && instance_read(:synced_to_s3)
|
||||
filesystem_paths.values.each do |filename|
|
||||
|
||||
@@ -34,10 +34,11 @@ module Paperclip
|
||||
def flush_writes #:nodoc:
|
||||
@queued_for_write.each do |style, file|
|
||||
file.close
|
||||
FileUtils.mkdir_p(File.dirname(path(style)))
|
||||
log("saving #{path(style)}")
|
||||
FileUtils.mv(file.path, path(style))
|
||||
FileUtils.chmod(0644, path(style))
|
||||
filename = path(style)
|
||||
FileUtils.mkdir_p(File.dirname(filename))
|
||||
log("saving #{filename}")
|
||||
FileUtils.mv(file.path, filename)
|
||||
FileUtils.chmod(0644, filename)
|
||||
end
|
||||
@queued_for_write = {}
|
||||
end
|
||||
|
||||
42
lib/paperclip/styles_parser.rb
Normal file
42
lib/paperclip/styles_parser.rb
Normal file
@@ -0,0 +1,42 @@
|
||||
module Paperclip
|
||||
class StylesParser
|
||||
attr_reader :styles, :convert_options, :processors, :whiny
|
||||
|
||||
def initialize(options)
|
||||
@styles = options[:styles]
|
||||
@convert_options = options[:convert_options] || {}
|
||||
@processors = options[:processors] || [:thumbnail]
|
||||
@whiny = options[:whiny_thumbnails] || options[:whiny]
|
||||
|
||||
normalize_style_definition
|
||||
end
|
||||
|
||||
def normalize_style_definition #:nodoc:
|
||||
styles.each do |name, args|
|
||||
styles[name] =
|
||||
if args.is_a? Hash
|
||||
{
|
||||
processors: processors,
|
||||
whiny: whiny,
|
||||
convert_options: extra_options_for(name)
|
||||
}.merge(args)
|
||||
else
|
||||
dimensions, format = args
|
||||
{
|
||||
processors: processors,
|
||||
geometry: dimensions,
|
||||
format: format.presence,
|
||||
whiny: whiny,
|
||||
convert_options: extra_options_for(name)
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def extra_options_for(style) #:nodoc:
|
||||
all_options = convert_options[:all]
|
||||
style_options = convert_options[style]
|
||||
[style_options, all_options].compact.join(' ')
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -17,5 +17,6 @@ Gem::Specification.new do |s|
|
||||
s.rubygems_version = %q{1.3.1}
|
||||
s.summary = %q{File attachments as attributes for ActiveRecord}
|
||||
|
||||
s.add_dependency 'activesupport'
|
||||
s.add_dependency 'fastimage'
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user