Permalink
Browse files

Add AttachementSizeValidator

  • Loading branch information...
1 parent 03f777f commit e83f88f3c310dc9889ee608ba4c4b524a8cd972c @sikachu sikachu committed Mar 9, 2012
View
@@ -2,23 +2,24 @@ PATH
remote: .
specs:
paperclip (2.7.0)
- activerecord (>= 2.3.0)
- activesupport (>= 2.3.2)
+ activemodel (>= 3.0.0)
+ activerecord (>= 3.0.0)
+ activesupport (>= 3.0.0)
cocaine (>= 0.0.2)
mime-types
GEM
remote: http://rubygems.org/
specs:
- activemodel (3.2.1)
- activesupport (= 3.2.1)
+ activemodel (3.2.2)
+ activesupport (= 3.2.2)
builder (~> 3.0.0)
- activerecord (3.2.1)
- activemodel (= 3.2.1)
- activesupport (= 3.2.1)
- arel (~> 3.0.0)
+ activerecord (3.2.2)
+ activemodel (= 3.2.2)
+ activesupport (= 3.2.2)
+ arel (~> 3.0.2)
tzinfo (~> 0.3.29)
- activesupport (3.2.1)
+ activesupport (3.2.2)
i18n (~> 0.6)
multi_json (~> 1.0)
appraisal (0.4.1)
@@ -111,7 +112,7 @@ GEM
shoulda (2.11.3)
sqlite3 (1.3.4)
term-ansicolor (1.0.7)
- tzinfo (0.3.31)
+ tzinfo (0.3.32)
uuidtools (2.1.2)
xpath (0.1.4)
nokogiri (~> 1.3)
View
@@ -195,31 +195,6 @@ def has_attached_file(name, options = {})
end
end
- # Places ActiveRecord-style validations on the size of the file assigned. The
- # possible options are:
- # * +in+: a Range of bytes (i.e. +1..1.megabyte+),
- # * +less_than+: equivalent to :in => 0..options[:less_than]
- # * +greater_than+: equivalent to :in => options[:greater_than]..Infinity
- # * +message+: error message to display, use :min and :max as replacements
- # * +if+: A lambda or name of an instance method. Validation will only
- # be run if this lambda or method returns true.
- # * +unless+: Same as +if+ but validates if lambda or method returns false.
- def validates_attachment_size name, options = {}
- min = options[:greater_than] || (options[:in] && options[:in].first) || 0
- max = options[:less_than] || (options[:in] && options[:in].last) || (1.0/0)
- range = (min..max)
- message = options[:message] || "must be between :min and :max bytes"
- message = message.call if message.respond_to?(:call)
- message = message.gsub(/:min/, min.to_s).gsub(/:max/, max.to_s)
-
- validates_inclusion_of :"#{name}_file_size",
- :in => range,
- :message => message,
- :if => options[:if],
- :unless => options[:unless],
- :allow_nil => true
- end
-
# Places ActiveRecord-style validations on the presence of a file.
# Options:
# * +if+: A lambda or name of an instance method. Validation will only
View
@@ -5,7 +5,11 @@ module Glue
def self.included base #:nodoc:
base.extend ClassMethods
base.send :include, Callbacks
+ base.send :include, Validators
base.class_attribute :attachment_definitions
+
+ locale_path = Dir.glob(File.dirname(__FILE__) + "/locales/*.{rb,yml}")
+ I18n.load_path += locale_path unless I18n.load_path.include?(locale_path)
end
end
end
@@ -0,0 +1,17 @@
+en:
+ errors:
+ messages:
+ in_between: "must be in between %{min} and %{max}"
+
+ number:
+ human:
+ storage_units:
+ format: "%n %u"
+ units:
+ byte:
+ one: "Byte"
+ other: "Bytes"
+ kb: "KB"
+ mb: "MB"
+ gb: "GB"
+ tb: "TB"
@@ -0,0 +1,13 @@
+require 'active_support/concern'
+require 'paperclip/validators/attachment_size_validator'
+
+module Paperclip
+ module Validators
+ extend ActiveSupport::Concern
+
+ included do
+ extend HelperMethods
+ include HelperMethods
+ end
+ end
+end
@@ -0,0 +1,96 @@
+require 'active_model/validations/numericality'
+
+module Paperclip
+ module Validators
+ class AttachmentSizeValidator < ActiveModel::Validations::NumericalityValidator
+ AVAILABLE_CHECKS = [:less_than, :less_than_or_equal_to, :greater_than, :greater_than_or_equal_to]
+
+ def initialize(options)
+ extract_options(options)
+ super
+ end
+
+ def validate_each(record, attr_name, value)
+ attr_name = "#{attr_name}_file_size".to_sym
+ value = record.send(:read_attribute_for_validation, attr_name)
+
+ unless value.blank?
+ options.slice(*AVAILABLE_CHECKS).each do |option, option_value|
+ option_value = option_value.call(record) if option_value.is_a?(Proc)
+ option_value = extract_option_value(option, option_value)
+
+ unless value.send(CHECKS[option], option_value)
+ error_message_key = options[:in] ? :in_between : option
+ record.errors.add(attr_name, error_message_key, filtered_options(value).merge(
+ :min => min_value_in_human_size(record),
+ :max => max_value_in_human_size(record),
+ :count => human_size(option_value)
+ ))
+ end
+ end
+ end
+ end
+
+ private
+
+ def extract_options(options)
+ if range = options[:in]
+ if !options[:in].respond_to?(:call)
+ options[:less_than_or_equal_to] = range.max
+ options[:greater_than_or_equal_to] = range.min
+ else
+ options[:less_than_or_equal_to] = range
+ options[:greater_than_or_equal_to] = range
+ end
+ end
+ end
+
+ def extract_option_value(option, option_value)
+ if option_value.is_a?(Range)
+ if [:less_than, :less_than_or_equal_to].include?(option)
+ option_value.max
+ else
+ option_value.min
+ end
+ else
+ option_value
+ end
+ end
+
+ def human_size(size)
+ storage_units_format = I18n.translate(:'number.human.storage_units.format', :locale => options[:locale], :raise => true)
+ unit = I18n.translate(:'number.human.storage_units.units.byte', :locale => options[:locale], :count => size.to_i, :raise => true)
+ storage_units_format.gsub(/%n/, size.to_i.to_s).gsub(/%u/, unit).html_safe
+ end
+
+ def min_value_in_human_size(record)
+ value = options[:greater_than_or_equal_to] || options[:greater_than]
+ value = value.call(record) if value.respond_to?(:call)
+ value = value.min if value.respond_to?(:min)
+ human_size(value)
+ end
+
+ def max_value_in_human_size(record)
+ value = options[:less_than_or_equal_to] || options[:less_than]
+ value = value.call(record) if value.respond_to?(:call)
+ value = value.max if value.respond_to?(:max)
+ human_size(value)
+ end
+ end
+
+ module HelperMethods
+ # Places ActiveRecord-style validations on the size of the file assigned. The
+ # possible options are:
+ # * +in+: a Range of bytes (i.e. +1..1.megabyte+),
+ # * +less_than+: equivalent to :in => 0..options[:less_than]
+ # * +greater_than+: equivalent to :in => options[:greater_than]..Infinity
+ # * +message+: error message to display, use :min and :max as replacements
+ # * +if+: A lambda or name of an instance method. Validation will only
+ # be run if this lambda or method returns true.
+ # * +unless+: Same as +if+ but validates if lambda or method returns false.
+ def validates_attachment_size(*attr_names)
+ validates_with AttachmentSizeValidator, _merge_attributes(attr_names)
+ end
+ end
+ end
+end
View
@@ -20,8 +20,9 @@ Gem::Specification.new do |s|
s.requirements << "ImageMagick"
- s.add_dependency('activerecord', '>= 2.3.0')
- s.add_dependency('activesupport', '>= 2.3.2')
+ s.add_dependency('activerecord', '>= 3.0.0')
+ s.add_dependency('activemodel', '>= 3.0.0')
+ s.add_dependency('activesupport', '>= 3.0.0')
s.add_dependency('cocaine', '>= 0.0.2')
s.add_dependency('mime-types')
View
@@ -9,11 +9,10 @@
require 'active_record'
require 'active_record/version'
require 'active_support'
+require 'active_support/core_ext'
require 'mime/types'
require 'pathname'
-require 'pathname'
-
puts "Testing against version #{ActiveRecord::VERSION::STRING}"
`ruby -e 'exit 0'` # Prime $? with a value.
View
@@ -354,22 +354,7 @@ def self.should_validate validation, options, valid_file, invalid_file
end
should "have a file size min/max error message" do
- assert [@dummy.errors[:avatar_file_size]].flatten.any?{|error| error =~ %r/between 0 and 10240 bytes/ }
- end
- end
- end
-
- context "with size validation and less_than 10240 option with lambda message" do
- context "and assigned an invalid file" do
- setup do
- Dummy.send(:"validates_attachment_size", :avatar, :less_than => 10240, :message => lambda {'lambda between 0 and 10240 bytes'})
- @dummy = Dummy.new
- @dummy.avatar &&= File.open(File.join(FIXTURES_DIR, "12k.png"), "rb")
- @dummy.valid?
- end
-
- should "have a file size min/max error message" do
- assert [@dummy.errors[:avatar_file_size]].flatten.any?{|error| error =~ %r/lambda between 0 and 10240 bytes/ }
+ assert_includes @dummy.errors[:avatar_file_size], "must be less than 10240 Bytes"
end
end
end
Oops, something went wrong.

0 comments on commit e83f88f

Please sign in to comment.