This repository has been archived by the owner on Jul 13, 2023. It is now read-only.
/
validate_attachment_size_matcher.rb
95 lines (79 loc) · 2.58 KB
/
validate_attachment_size_matcher.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
module Paperclip
module Shoulda
module Matchers
# Ensures that the given instance or class validates the size of the
# given attachment as specified.
#
# Examples:
# it { should validate_attachment_size(:avatar).
# less_than(2.megabytes) }
# it { should validate_attachment_size(:icon).
# greater_than(1024) }
# it { should validate_attachment_size(:icon).
# in(0..100) }
def validate_attachment_size name
ValidateAttachmentSizeMatcher.new(name)
end
class ValidateAttachmentSizeMatcher
def initialize attachment_name
@attachment_name = attachment_name
@low, @high = 0, (1.0/0)
end
def less_than size
@high = size
self
end
def greater_than size
@low = size
self
end
def in range
@low, @high = range.first, range.last
self
end
def matches? subject
@subject = subject
@subject = @subject.new if @subject.class == Class
lower_than_low? && higher_than_low? && lower_than_high? && higher_than_high?
end
def failure_message
"Attachment #{@attachment_name} must be between #{@low} and #{@high} bytes"
end
def negative_failure_message
"Attachment #{@attachment_name} cannot be between #{@low} and #{@high} bytes"
end
def description
"validate the size of attachment #{@attachment_name}"
end
protected
def override_method object, method, &replacement
(class << object; self; end).class_eval do
define_method(method, &replacement)
end
end
def passes_validation_with_size(new_size)
file = StringIO.new(".")
override_method(file, :size){ new_size }
override_method(file, :to_tempfile){ file }
@subject.send(@attachment_name).assign(file)
@subject.valid?
@subject.errors[:"#{@attachment_name}_file_size"].blank?
end
def lower_than_low?
not passes_validation_with_size(@low - 1)
end
def higher_than_low?
passes_validation_with_size(@low + 1)
end
def lower_than_high?
return true if @high == (1.0/0)
passes_validation_with_size(@high - 1)
end
def higher_than_high?
return true if @high == (1.0/0)
not passes_validation_with_size(@high + 1)
end
end
end
end
end