lib/paperclip/has_attached_file.rb
module Paperclip
class HasAttachedFile
def self.define_on(klass, name, options)
new(klass, name, options).define
end
def initialize(klass, name, options)
@klass = klass
@name = name
@options = options
end
def define
define_flush_errors
define_getters
define_setter
define_query
register_new_attachment
add_active_record_callbacks
add_paperclip_callbacks
add_required_validations
end
private
def define_flush_errors
@klass.send(:validates_each, @name) do |record, attr, value|
attachment = record.send(@name)
attachment.send(:flush_errors)
end
end
def define_getters
define_instance_getter
define_class_getter
end
def define_instance_getter
name = @name
options = @options
@klass.send :define_method, @name do |*args|
ivar = "@attachment_#{name}"
attachment = instance_variable_get(ivar)
if attachment.nil?
attachment = Attachment.new(name, self, options)
instance_variable_set(ivar, attachment)
end
if args.length > 0
attachment.to_s(args.first)
else
attachment
end
end
end
def define_class_getter
@klass.extend(ClassMethods)
end
def define_setter
name = @name
@klass.send :define_method, "#{@name}=" do |file|
send(name).assign(file)
end
end
def define_query
name = @name
@klass.send :define_method, "#{@name}?" do
send(name).file?
end
end
def register_new_attachment
Paperclip::AttachmentRegistry.register(@klass, @name, @options)
end
def add_required_validations
options = Paperclip::Attachment.default_options.deep_merge(@options)
if options[:validate_media_type] != false
name = @name
@klass.validates_media_type_spoof_detection name,
:if => ->(instance){ instance.send(name).dirty? }
end
end
def add_active_record_callbacks
name = @name
@klass.send(:after_save) { send(name).send(:save) }
@klass.send(:before_destroy) { send(name).send(:queue_all_for_delete) }
if @klass.respond_to?(:after_commit)
@klass.send(:after_commit, on: :destroy) do
send(name).send(:flush_deletes)
end
else
@klass.send(:after_destroy) { send(name).send(:flush_deletes) }
end
end
def add_paperclip_callbacks
@klass.send(
:define_paperclip_callbacks,
:post_process, :"#{@name}_post_process")
end
module ClassMethods
def attachment_definitions
Paperclip::AttachmentRegistry.definitions_for(self)
end
end
end
end