forked from formtastic/formtastic
-
Notifications
You must be signed in to change notification settings - Fork 0
/
validations.rb
197 lines (167 loc) · 6.94 KB
/
validations.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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
module Formtastic
module Inputs
module Base
module Validations
class IndeterminableMinimumAttributeError < ArgumentError
def message
[
"A minimum value can not be determined when the validation uses :greater_than on a :decimal or :float column type.",
"Please alter the validation to use :greater_than_or_equal_to, or provide a value for this attribute explicitly with the :min option on input()."
].join("\n")
end
end
class IndeterminableMaximumAttributeError < ArgumentError
def message
[
"A maximum value can not be determined when the validation uses :less_than on a :decimal or :float column type.",
"Please alter the validation to use :less_than_or_equal_to, or provide a value for this attribute explicitly with the :max option on input()."
].join("\n")
end
end
def validations
@validations ||= if object && object.class.respond_to?(:validators_on)
object.class.validators_on(attributized_method_name).select do |validator|
validator_relevant?(validator)
end
else
nil
end
end
def validator_relevant?(validator)
return true unless validator.options.key?(:if) || validator.options.key?(:unless)
conditional = validator.options.key?(:if) ? validator.options[:if] : validator.options[:unless]
result = if conditional.respond_to?(:call)
conditional.call(object)
elsif conditional.is_a?(::Symbol) && object.respond_to?(conditional)
object.send(conditional)
else
conditional
end
result = validator.options.key?(:unless) ? !result : !!result
not_required_through_negated_validation! if !result && [:presence, :inclusion, :length].include?(validator.kind)
result
end
def validation_limit
validation = validations? && validations.find do |validation|
validation.kind == :length
end
if validation
validation.options[:maximum] || (validation.options[:within].present? ? validation.options[:within].max : nil)
else
nil
end
end
# Prefer :greater_than_or_equal_to over :greater_than, for no particular reason.
def validation_min
validation = validations? && validations.find do |validation|
validation.kind == :numericality
end
if validation
# We can't determine an appropriate value for :greater_than with a float/decimal column
raise IndeterminableMinimumAttributeError if validation.options[:greater_than] && column? && [:float, :decimal].include?(column.type)
if validation.options[:greater_than_or_equal_to]
return (validation.options[:greater_than_or_equal_to].call(object)) if validation.options[:greater_than_or_equal_to].kind_of?(Proc)
return (validation.options[:greater_than_or_equal_to])
end
if validation.options[:greater_than]
return (validation.options[:greater_than].call(object) + 1) if validation.options[:greater_than].kind_of?(Proc)
return (validation.options[:greater_than] + 1)
end
end
end
# Prefer :less_than_or_equal_to over :less_than, for no particular reason.
def validation_max
validation = validations? && validations.find do |validation|
validation.kind == :numericality
end
if validation
# We can't determine an appropriate value for :greater_than with a float/decimal column
raise IndeterminableMaximumAttributeError if validation.options[:less_than] && column? && [:float, :decimal].include?(column.type)
if validation.options[:less_than_or_equal_to]
return (validation.options[:less_than_or_equal_to].call(object)) if validation.options[:less_than_or_equal_to].kind_of?(Proc)
return (validation.options[:less_than_or_equal_to])
end
if validation.options[:less_than]
return ((validation.options[:less_than].call(object)) - 1) if validation.options[:less_than].kind_of?(Proc)
return (validation.options[:less_than] - 1)
end
end
end
def validation_step
validation = validations? && validations.find do |validation|
validation.kind == :numericality
end
if validation
validation.options[:step] || (1 if validation_integer_only?)
else
nil
end
end
def validation_integer_only?
validation = validations? && validations.find do |validation|
validation.kind == :numericality
end
if validation
validation.options[:only_integer]
else
false
end
end
def validations?
validations != nil
end
def required?
return false if options[:required] == false
return true if options[:required] == true
return false if not_required_through_negated_validation?
if validations?
validations.select { |validator|
if validator.options.key?(:on)
return false if (validator.options[:on] != :save) && ((object.new_record? && validator.options[:on] != :create) || (!object.new_record? && validator.options[:on] != :update))
end
case validator.kind
when :presence
true
when :inclusion
validator.options[:allow_blank] != true
when :length
validator.options[:allow_blank] != true &&
validator.options[:minimum].to_i > 0 ||
validator.options[:within].try(:first).to_i > 0
else
false
end
}.any?
else
return responds_to_global_required? && !!builder.all_fields_required_by_default
end
end
def required_attribute?
required? && builder.use_required_attribute
end
def not_required_through_negated_validation?
@not_required_through_negated_validation
end
def not_required_through_negated_validation!
@not_required_through_negated_validation = true
end
def responds_to_global_required?
true
end
def optional?
!required?
end
def autofocus?
opt_autofocus = options[:input_html] && options[:input_html][:autofocus]
!!opt_autofocus
end
def column_limit
column.limit if column? && column.respond_to?(:limit)
end
def limit
validation_limit || column_limit
end
end
end
end
end