Commit 2aeb491f by Dan Collis-Puro Committed by Jon Yurek

Add content_type and size errors to base attribute

This propagates attachment size and content_type validations to the main
attachment attribute, to make them behave the same as presence
validations. This allows paperclip to play more nicely with simple_form
and other form abstraction gems.

This commit includes a behaviorial change. If you emit all errors on a
model instance you will see some failed validations twice: once for the
base attachment attribute and again for the failed presence,
content_type or size attachment attributes.
parent edea587f
...@@ -7,29 +7,31 @@ module Paperclip ...@@ -7,29 +7,31 @@ module Paperclip
end end
def validate_each(record, attribute, value) def validate_each(record, attribute, value)
base_attribute = attribute.to_sym
attribute = "#{attribute}_content_type".to_sym attribute = "#{attribute}_content_type".to_sym
value = record.send :read_attribute_for_validation, attribute value = record.send :read_attribute_for_validation, attribute
return if (value.nil? && options[:allow_nil]) || (value.blank? && options[:allow_blank]) return if (value.nil? && options[:allow_nil]) || (value.blank? && options[:allow_blank])
validate_whitelist(record, attribute, value) validate_whitelist(record, base_attribute, attribute, value)
validate_blacklist(record, attribute, value) validate_blacklist(record, base_attribute, attribute, value)
end end
def validate_whitelist(record, attribute, value) def validate_whitelist(record, base_attribute, attribute, value)
if allowed_types.present? && allowed_types.none? { |type| type === value } if allowed_types.present? && allowed_types.none? { |type| type === value }
mark_invalid record, attribute, allowed_types mark_invalid record, base_attribute, attribute, allowed_types
end end
end end
def validate_blacklist(record, attribute, value) def validate_blacklist(record, base_attribute, attribute, value)
if forbidden_types.present? && forbidden_types.any? { |type| type === value } if forbidden_types.present? && forbidden_types.any? { |type| type === value }
mark_invalid record, attribute, forbidden_types mark_invalid record, base_attribute, attribute, forbidden_types
end end
end end
def mark_invalid(record, attribute, types) def mark_invalid(record, base_attribute, attribute, types)
record.errors.add attribute, :invalid, options.merge(:types => types.join(', ')) record.errors.add attribute, :invalid, options.merge(:types => types.join(', '))
record.errors.add base_attribute, :invalid, options.merge(:types => types.join(', '))
end end
def allowed_types def allowed_types
......
...@@ -11,6 +11,7 @@ module Paperclip ...@@ -11,6 +11,7 @@ module Paperclip
end end
def validate_each(record, attr_name, value) def validate_each(record, attr_name, value)
base_attr_name = attr_name
attr_name = "#{attr_name}_file_size".to_sym attr_name = "#{attr_name}_file_size".to_sym
value = record.send(:read_attribute_for_validation, attr_name) value = record.send(:read_attribute_for_validation, attr_name)
...@@ -21,11 +22,13 @@ module Paperclip ...@@ -21,11 +22,13 @@ module Paperclip
unless value.send(CHECKS[option], option_value) unless value.send(CHECKS[option], option_value)
error_message_key = options[:in] ? :in_between : option error_message_key = options[:in] ? :in_between : option
record.errors.add(attr_name, error_message_key, filtered_options(value).merge( [ attr_name, base_attr_name ].each do |error_attr_name|
:min => min_value_in_human_size(record), record.errors.add(error_attr_name, error_message_key, filtered_options(value).merge(
:max => max_value_in_human_size(record), :min => min_value_in_human_size(record),
:count => human_size(option_value) :max => max_value_in_human_size(record),
)) :count => human_size(option_value)
))
end
end end
end end
end end
......
...@@ -50,6 +50,32 @@ class AttachmentContentTypeValidatorTest < Test::Unit::TestCase ...@@ -50,6 +50,32 @@ class AttachmentContentTypeValidatorTest < Test::Unit::TestCase
end end
end end
context "with a failing validation" do
setup do
build_validator :content_type => "image/png", :allow_nil => false
@dummy.stubs(:avatar_content_type => nil)
@validator.validate(@dummy)
end
should "add error to the base object" do
assert @dummy.errors[:avatar].present?,
"Error not added to base attribute"
end
end
context "with a successful validation" do
setup do
build_validator :content_type => "image/png", :allow_nil => false
@dummy.stubs(:avatar_content_type => "image/png")
@validator.validate(@dummy)
end
should "not add error to the base object" do
assert @dummy.errors[:avatar].blank?,
"Error was added to base attribute"
end
end
context "with :allow_blank option" do context "with :allow_blank option" do
context "as true" do context "as true" do
setup do setup do
......
...@@ -20,6 +20,11 @@ class AttachmentSizeValidatorTest < Test::Unit::TestCase ...@@ -20,6 +20,11 @@ class AttachmentSizeValidatorTest < Test::Unit::TestCase
assert @dummy.errors[:avatar_file_size].blank?, assert @dummy.errors[:avatar_file_size].blank?,
"Expect an error message on :avatar_file_size, got none." "Expect an error message on :avatar_file_size, got none."
end end
should "not add error to the base dummy object" do
assert @dummy.errors[:avatar].blank?,
"Error added to base attribute"
end
end end
end end
...@@ -35,6 +40,11 @@ class AttachmentSizeValidatorTest < Test::Unit::TestCase ...@@ -35,6 +40,11 @@ class AttachmentSizeValidatorTest < Test::Unit::TestCase
"Unexpected error message on :avatar_file_size" "Unexpected error message on :avatar_file_size"
end end
should "add error to the base dummy object" do
assert @dummy.errors[:avatar].present?,
"Error not added to base attribute"
end
if options[:message] if options[:message]
should "return a correct error message" do should "return a correct error message" do
assert_includes @dummy.errors[:avatar_file_size], options[:message] assert_includes @dummy.errors[:avatar_file_size], options[:message]
......
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