Permalink
Browse files

Validation bug fixes:

 * Errors reported get keyed with the correct property so that
   form_for correctly decorates them on error.
 * Properly detecting file extensions when given Rails UploadedFile
   objects.
  • Loading branch information...
1 parent 87c5105 commit 750dc165fa5713fff7f6caf733f528204d27fdb4 @hdeshev hdeshev committed Jan 6, 2012
Showing with 70 additions and 41 deletions.
  1. +1 −0 Gemfile
  2. +6 −5 Gemfile.lock
  3. +0 −17 lib/filer/activerecord.rb
  4. +3 −2 lib/filer/attachment.rb
  5. +29 −13 lib/filer/validation.rb
  6. +7 −0 test/file_like.rb
  7. +22 −2 test/test_validation.rb
  8. +2 −2 test/user_data.rb
View
1 Gemfile
@@ -19,6 +19,7 @@ group :development do
end
gem "activerecord", ">=3.0.0"
+gem "activemodel", ">=3.0.0"
gem "uuid"
gem "rest-client"
gem "multi_json"
View
11 Gemfile.lock
@@ -16,19 +16,19 @@ GEM
builder (3.0.0)
ffi (1.0.11)
git (1.2.5)
- guard (0.9.1)
+ guard (0.10.0)
ffi (>= 0.5.0)
thor (~> 0.14.6)
- guard-test (0.4.2)
+ guard-test (0.4.3)
guard (>= 0.4)
test-unit (~> 2.2)
i18n (0.6.0)
jeweler (1.6.4)
bundler (~> 1.0)
git (>= 1.2.5)
rake
- json (1.6.3)
- libnotify (0.6.0)
+ json (1.6.4)
+ libnotify (0.7.1)
macaddr (1.5.0)
systemu (>= 2.4.0)
mime-types (1.17.2)
@@ -44,7 +44,7 @@ GEM
shoulda (2.11.3)
sqlite3 (1.3.5)
systemu (2.4.2)
- test-unit (2.4.3)
+ test-unit (2.4.4)
thor (0.14.6)
tzinfo (0.3.31)
uuid (2.3.4)
@@ -54,6 +54,7 @@ PLATFORMS
ruby
DEPENDENCIES
+ activemodel (>= 3.0.0)
activerecord (>= 3.0.0)
bundler (~> 1.0.0)
guard-test
View
17 lib/filer/activerecord.rb
@@ -36,23 +36,6 @@ def upload_#{attribute}!
_uploaders[attribute] = uploaderClass.new
end
-
- def validates_file_extension(attribute, options)
- allowed = options[:allowed] || EverythingIncluded.new
- message = options[:message] || "File extension not allowed for '#{attribute}'."
-
- validates_inclusion_of :"#{attribute}_file_extension",
- :in => allowed,
- :message => message,
- :allow_blank => true,
- :allow_nil => true
- end
-
- class EverythingIncluded
- def include?
- true
- end
- end
end
module ActiveRecordInstanceMethods
View
5 lib/filer/attachment.rb
@@ -45,11 +45,12 @@ def size
end
def path
- file.path
+ (file.original_filename if file.respond_to?(:original_filename)) ||
+ (file_path = file.path if file.respond_to?(:path))
end
def extension
- from_file = File.extname(file.path) || ""
+ from_file = File.extname(path) || ""
from_file.sub(".", "")
end
View
42 lib/filer/validation.rb
@@ -1,34 +1,50 @@
+require 'active_model'
+
module Progstr
module Filer
module Validation
- def validates_file_size(attribute, options)
+ def validates_file_size_of(attribute, options)
range = options[:in] || (0..1.0/0)
min = options[:greater_than] || range.first
max = options[:less_than] || range.last
allowed_range = (min..max)
message = options[:message] || "File size not between #{min} and #{max} bytes."
- validates_inclusion_of :"#{attribute}_file_size",
+ validates_with PropertyValidator, :attributes => [attribute],
+ :property => :size,
:in => allowed_range,
:message => message,
:allow_blank => true,
:allow_nil => true
end
- def validates_file_size(attribute, options)
- range = options[:in] || (0..1.0/0)
- min = options[:greater_than] || range.first
- max = options[:less_than] || range.last
- allowed_range = (min..max)
+ def validates_file_extension_of(attribute, options)
+ allowed = options[:allowed] || EverythingIncluded.new
+ message = options[:message] || "File extension not allowed."
- message = options[:message] || "File size not between #{min} and #{max} bytes for '#{attribute}'."
+ validates_with PropertyValidator, :attributes => [attribute],
+ :property => :extension,
+ :in => allowed,
+ :message => message
+ end
- validates_inclusion_of :"#{attribute}_file_size",
- :in => allowed_range,
- :message => message,
- :allow_blank => true,
- :allow_nil => true
+ class EverythingIncluded
+ def include?
+ true
+ end
+ end
+
+ class PropertyValidator < ActiveModel::Validations::InclusionValidator
+ def initialize(options)
+ @property = options[:property]
+ super(options)
+ end
+
+ def validate_each(record, attribute, value)
+ property_value = value.send(@property)
+ super(record, attribute, property_value) unless value.nil? || value.blank? || property_value.nil?
+ end
end
end
end
View
7 test/file_like.rb
@@ -6,3 +6,10 @@ def read
end
end
+class UploadedFileLike
+ attr_accessor :size, :original_filename
+
+ def read
+ "contents"
+ end
+end
View
24 test/test_validation.rb
@@ -13,7 +13,7 @@ class TestValidation < UserTest
too_big.size = 5 * 1024 * 1024
u.avatar = too_big
assert_false u.valid?, "User not valid with huge avatar"
- assert_equal u.errors[:avatar_file_size], ["Not uploading more than 2 MB."]
+ assert_equal u.errors[:avatar], ["Not uploading more than 2 MB."]
end
test "don't store if extension not allowed" do
@@ -23,7 +23,27 @@ class TestValidation < UserTest
u.avatar = exe
assert_false u.valid?, "User not valid with 'exe' avatar extension."
- assert_equal u.errors[:avatar_file_extension], ["Avatar image extension not allowed."]
+ assert_equal u.errors[:avatar], ["Avatar image extension not allowed."]
+ end
+
+ test "use original_filename on file objects if present" do
+ u = ValidatedUser.new
+ exe = UploadedFileLike.new
+ exe.original_filename = "virus_infected.exe"
+ u.avatar = exe
+
+ assert_false u.valid?, "User not valid with 'exe' avatar extension."
+ assert_equal u.errors[:avatar], ["Avatar image extension not allowed."]
+ end
+
+ test "don't store files without an extension" do
+ u = ValidatedUser.new
+ exe = FileLike.new
+ exe.path = "noextension"
+ u.avatar = exe
+
+ assert_false u.valid?, "User not valid with an avatar without a file extension."
+ assert_equal u.errors[:avatar], ["Avatar image extension not allowed."]
end
test "validation passes" do
View
4 test/user_data.rb
@@ -38,10 +38,10 @@ class User < ActiveRecord::Base
class ValidatedUser < User
validates_presence_of :avatar
- validates_file_size :avatar,
+ validates_file_size_of :avatar,
:less_than => 2 * 1024 * 1024,
:message => "Not uploading more than 2 MB."
- validates_file_extension :avatar, :allowed => ["png", "jpg"],
+ validates_file_extension_of :avatar, :allowed => ["png", "jpg"],
:message => "Avatar image extension not allowed."
end

0 comments on commit 750dc16

Please sign in to comment.