Commit da5d716b by Prem Sichanugrist

Add AttachmentContentTypeValidator

parent ee42b198
......@@ -195,40 +195,6 @@ module Paperclip
end
end
# Places ActiveRecord-style validations on the content type of the file
# assigned. The possible options are:
# * +content_type+: Allowed content types. Can be a single content type
# or an array. Each type can be a String or a Regexp. It should be
# noted that Internet Explorer uploads files with content_types that you
# may not expect. For example, JPEG images are given image/pjpeg and
# PNGs are image/x-png, so keep that in mind when determining how you
# match. Allows all by default.
# * +message+: The message to display when the uploaded file has an invalid
# content type.
# * +if+: A lambda or name of an instance method. Validation will only
# be run is this lambda or method returns true.
# * +unless+: Same as +if+ but validates if lambda or method returns false.
# 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.
# You'll still need to have a virtual attribute (created by +attr_accessor+)
# name +[attachment]_content_type+ to be able to use this validator.
def validates_attachment_content_type name, options = {}
validation_options = options.dup
allowed_types = [validation_options[:content_type]].flatten
validates_each(:"#{name}_content_type", validation_options) do |record, attr, value|
if !allowed_types.any?{|t| t === value } && !(value.nil? || value.blank?)
if record.errors.method(:add).arity == -2
message = options[:message] || "is not one of #{allowed_types.join(", ")}"
message = message.call if message.respond_to?(:call)
record.errors.add(:"#{name}_content_type", message)
else
record.errors.add(:"#{name}_content_type", :inclusion, :default => options[:message], :value => value)
end
end
end
end
# Returns the attachment definitions defined by each call to
# has_attached_file.
def attachment_definitions
......
require 'active_support/concern'
require 'paperclip/validators/attachment_content_type_validator'
require 'paperclip/validators/attachment_presence_validator'
require 'paperclip/validators/attachment_size_validator'
......
module Paperclip
module Validators
class AttachmentContentTypeValidator < ActiveModel::EachValidator
def validate_each(record, attribute, value)
attribute = "#{attribute}_content_type".to_sym
value = record.send(:read_attribute_for_validation, attribute)
allowed_types = [options[:content_type]].flatten
unless value.blank?
allowed_types.any? do |type|
unless type === value
record.errors.add(attribute, :invalid, options.merge(
:types => allowed_types.join(', ')
))
end
end
end
end
end
module HelperMethods
# Places ActiveRecord-style validations on the content type of the file
# assigned. The possible options are:
# * +content_type+: Allowed content types. Can be a single content type
# or an array. Each type can be a String or a Regexp. It should be
# noted that Internet Explorer uploads files with content_types that you
# may not expect. For example, JPEG images are given image/pjpeg and
# PNGs are image/x-png, so keep that in mind when determining how you
# match. Allows all by default.
# * +message+: The message to display when the uploaded file has an invalid
# content type.
# * +if+: A lambda or name of an instance method. Validation will only
# be run is this lambda or method returns true.
# * +unless+: Same as +if+ but validates if lambda or method returns false.
# 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.
# You'll still need to have a virtual attribute (created by +attr_accessor+)
# name +[attachment]_content_type+ to be able to use this validator.
def validates_attachment_content_type(*attr_names)
validates_with AttachmentContentTypeValidator, _merge_attributes(attr_names)
end
end
end
end
......@@ -329,21 +329,6 @@ class PaperclipTest < Test::Unit::TestCase
should_validate validation, options, valid_file, invalid_file
end
context "with content_type validation and lambda message" do
context "and assigned an invalid file" do
setup do
Dummy.send(:"validates_attachment_content_type", :avatar, :content_type => %r{image/.*}, :message => lambda {'lambda content type message'})
@dummy = Dummy.new
@dummy.avatar &&= File.open(File.join(FIXTURES_DIR, "text.txt"), "rb")
@dummy.valid?
end
should "have a content type error message" do
assert [@dummy.errors[:avatar_content_type]].flatten.any?{|error| error =~ %r/lambda content type message/ }
end
end
end
context "with size validation and less_than 10240 option" do
context "and assigned an invalid file" do
setup do
......
require './test/helper'
class AttachmentContentTypeValidatorTest < Test::Unit::TestCase
def setup
rebuild_model
@dummy = Dummy.new
end
def build_validator(options)
@validator = Paperclip::Validators::AttachmentContentTypeValidator.new(options.merge(
:attributes => :avatar
))
end
context "with a nil content type" do
setup do
build_validator :content_type => "image/jpg"
@dummy.stubs(:avatar_content_type => nil)
@validator.validate(@dummy)
end
should "not set an error message" do
assert @dummy.errors[:avatar_content_type].blank?
end
end
context "with an allowed type" do
context "as a string" do
setup do
build_validator :content_type => "image/jpg"
@dummy.stubs(:avatar_content_type => "image/jpg")
@validator.validate(@dummy)
end
should "not set an error message" do
assert @dummy.errors[:avatar_content_type].blank?
end
end
context "as an regexp" do
setup do
build_validator :content_type => /^image\/.*/
@dummy.stubs(:avatar_content_type => "image/jpg")
@validator.validate(@dummy)
end
should "not set an error message" do
assert @dummy.errors[:avatar_content_type].blank?
end
end
end
context "with a disallowed type" do
context "as a string" do
setup do
build_validator :content_type => "image/png"
@dummy.stubs(:avatar_content_type => "image/jpg")
@validator.validate(@dummy)
end
should "set a correct default error message" do
assert @dummy.errors[:avatar_content_type].present?
assert_includes @dummy.errors[:avatar_content_type], "is invalid"
end
end
context "as a regexp" do
setup do
build_validator :content_type => /^text\/.*/
@dummy.stubs(:avatar_content_type => "image/jpg")
@validator.validate(@dummy)
end
should "set a correct default error message" do
assert @dummy.errors[:avatar_content_type].present?
assert_includes @dummy.errors[:avatar_content_type], "is invalid"
end
end
context "with :message option" do
context "without interpolation" do
setup do
build_validator :content_type => "image/png", :message => "should be a PNG image"
@dummy.stubs(:avatar_content_type => "image/jpg")
@validator.validate(@dummy)
end
should "set a correct error message" do
assert_includes @dummy.errors[:avatar_content_type], "should be a PNG image"
end
end
context "with interpolation" do
setup do
build_validator :content_type => "image/png", :message => "should have content type %{types}"
@dummy.stubs(:avatar_content_type => "image/jpg")
@validator.validate(@dummy)
end
should "set a correct error message" do
assert_includes @dummy.errors[:avatar_content_type], "should have content type image/png"
end
end
end
end
end
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