Skip to content
Browse files

Refactored validations to not use lambdas. Added :if and :unless guar…

…d clauses.
  • Loading branch information...
1 parent f22d78f commit 4fc132f0cfacdc1389bba1d14883bd601b1a33f9 @jyurek jyurek committed May 6, 2009
Showing with 99 additions and 25 deletions.
  1. +12 −22 lib/paperclip.rb
  2. +37 −3 lib/paperclip/attachment.rb
  3. +50 −0 test/paperclip_test.rb
View
34 lib/paperclip.rb
@@ -44,7 +44,7 @@
# 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 @@ def has_attached_file name, options = {}
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 @@ def validates_attachment_size name, options = {}
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 @@ def validates_attachment_thumbnails name, options = {}
# 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 @@ def validates_attachment_presence name, options = {}
# 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
View
40 lib/paperclip/attachment.rb
@@ -11,7 +11,7 @@ def self.default_options
:styles => {},
:default_url => "/:attachment/:style/missing.png",
:default_style => :original,
- :validations => {},
+ :validations => [],
:storage => :filesystem
}
end
@@ -269,8 +269,8 @@ def valid_assignment? file #:nodoc:
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 @@ def validate #:nodoc:
@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
View
50 test/paperclip_test.rb
@@ -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 ::SubDummy < Dummy; end
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

0 comments on commit 4fc132f

Please sign in to comment.
Something went wrong with that request. Please try again.