Commit 4fc132f0 by Jon Yurek

Refactored validations to not use lambdas. Added :if and :unless guard clauses.

parent f22d78f3
......@@ -44,7 +44,7 @@ end
# documentation for Paperclip::ClassMethods for more useful information.
module Paperclip
VERSION = "2.2.8"
VERSION = "2.2.9"
class << self
# Provides configurability to Paperclip. There are a number of options available, such as:
......@@ -188,7 +188,7 @@ module Paperclip
include InstanceMethods
write_inheritable_attribute(:attachment_definitions, {}) if attachment_definitions.nil?
attachment_definitions[name] = {:validations => {}}.merge(options)
attachment_definitions[name] = {:validations => []}.merge(options)
after_save :save_attached_files
before_destroy :destroy_attached_files
......@@ -227,11 +227,10 @@ module Paperclip
range = (min..max)
message = options[:message] || "file size must be between :min and :max bytes."
attachment_definitions[name][:validations][:size] = lambda do |attachment, instance|
if attachment.file? && !range.include?(attachment.size.to_i)
message.gsub(/:min/, min.to_s).gsub(/:max/, max.to_s)
end
end
attachment_definitions[name][:validations] << [:size, {:range => range,
:message => message,
:if => options[:if],
:unless => options[:unless]}]
end
# Adds errors if thumbnail creation fails. The same as specifying :whiny_thumbnails => true.
......@@ -242,9 +241,9 @@ module Paperclip
# Places ActiveRecord-style validations on the presence of a file.
def validates_attachment_presence name, options = {}
message = options[:message] || "must be set."
attachment_definitions[name][:validations][:presence] = lambda do |attachment, instance|
message unless attachment.file?
end
attachment_definitions[name][:validations] << [:presence, {:message => message,
:if => options[:if],
:unless => options[:unless]}]
end
# Places ActiveRecord-style validations on the content type of the file
......@@ -261,18 +260,9 @@ module Paperclip
# 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] = lambda do |attachment, instance|
valid_types = [options[:content_type]].flatten
unless attachment.original_filename.blank?
unless valid_types.blank?
content_type = attachment.instance_read(:content_type)
unless valid_types.any?{|t| content_type.nil? || t === content_type }
options[:message] || "is not one of the allowed file types."
end
end
end
end
attachment_definitions[name][:validations] << [:content_type, {:content_type => options[:content_type],
:if => options[:if],
:unless => options[:unless]}]
end
# Returns the attachment definitions defined by each call to
......
......@@ -11,7 +11,7 @@ module Paperclip
:styles => {},
:default_url => "/:attachment/:style/missing.png",
:default_style => :original,
:validations => {},
:validations => [],
:storage => :filesystem
}
end
......@@ -269,8 +269,8 @@ module Paperclip
def validate #:nodoc:
unless @validation_errors
@validation_errors = @validations.inject({}) do |errors, validation|
name, block = validation
errors[name] = block.call(self, instance) if block
name, options = validation
errors[name] = send(:"validate_#{name}", options) if allow_validation?(options)
errors
end
@validation_errors.reject!{|k,v| v == nil }
......@@ -279,6 +279,40 @@ module Paperclip
@validation_errors
end
def allow_validation? options
(options[:if].nil? || check_guard(options[:if])) && (options[:unless].nil? || !check_guard(options[:unless]))
end
def check_guard guard
if guard.respond_to? :call
guard.call(instance)
elsif ! guard.blank?
instance.send(guard.to_s)
end
end
def validate_size options #:nodoc:
if file? && !options[:range].include?(size.to_i)
options[:message].gsub(/:min/, options[:min].to_s).gsub(/:max/, options[:max].to_s)
end
end
def validate_presence options #:nodoc:
options[:message] unless file?
end
def validate_content_type options #:nodoc:
valid_types = [options[:content_type]].flatten
unless original_filename.blank?
unless valid_types.blank?
content_type = instance_read(:content_type)
unless valid_types.any?{|t| content_type.nil? || t === content_type }
options[:message] || "is not one of the allowed file types."
end
end
end
end
def normalize_style_definition #:nodoc:
@styles.each do |name, args|
unless args.is_a? Hash
......
......@@ -44,6 +44,18 @@ class PaperclipTest < Test::Unit::TestCase
assert_equal ::Paperclip::Thumbnail, Paperclip.processor(:thumbnail)
end
should "call a proc sent to check_guard" do
@dummy = Dummy.new
@dummy.expects(:one).returns(:one)
assert_equal :one, @dummy.avatar.send(:check_guard, lambda{|x| x.one })
end
should "call a method name sent to check_guard" do
@dummy = Dummy.new
@dummy.expects(:one).returns(:one)
assert_equal :one, @dummy.avatar.send(:check_guard, :one)
end
context "Paperclip.bit_bucket" do
context "on systems without /dev/null" do
setup do
......@@ -167,6 +179,44 @@ class PaperclipTest < Test::Unit::TestCase
end
end
context "a validation with an if guard clause" do
setup do
Dummy.send(:"validates_attachment_presence", :avatar, :if => lambda{|i| i.foo })
@dummy = Dummy.new
end
should "attempt validation if the guard returns true" do
@dummy.expects(:foo).returns(true)
@dummy.avatar.expects(:validate_presence).returns(nil)
@dummy.valid?
end
should "not attempt validation if the guard returns false" do
@dummy.expects(:foo).returns(false)
@dummy.avatar.expects(:validate_presence).never
@dummy.valid?
end
end
context "a validation with an unless guard clause" do
setup do
Dummy.send(:"validates_attachment_presence", :avatar, :unless => lambda{|i| i.foo })
@dummy = Dummy.new
end
should "attempt validation if the guard returns true" do
@dummy.expects(:foo).returns(false)
@dummy.avatar.expects(:validate_presence).returns(nil)
@dummy.valid?
end
should "not attempt validation if the guard returns false" do
@dummy.expects(:foo).returns(true)
@dummy.avatar.expects(:validate_presence).never
@dummy.valid?
end
end
def self.should_validate validation, options, valid_file, invalid_file
context "with #{validation} validation and #{options.inspect} options" do
setup do
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment