| Module | Sequel::Plugins::ValidationClassMethods::ClassMethods |
| In: |
lib/sequel/plugins/validation_class_methods.rb
|
| validations | [R] | A hash of associations for this model class. Keys are column symbols, values are arrays of validation procs. |
Returns true if validations are defined.
# File lib/sequel/plugins/validation_class_methods.rb, line 48
48: def has_validations?
49: !validations.empty?
50: end
Setup the validations hash in the subclass
# File lib/sequel/plugins/validation_class_methods.rb, line 53
53: def inherited(subclass)
54: super
55: subclass.class_eval do
56: @validation_mutex = Mutex.new
57: @validations = {}
58: end
59: end
Instructs the model to skip validations defined in superclasses
# File lib/sequel/plugins/validation_class_methods.rb, line 62
62: def skip_superclass_validations
63: @skip_superclass_validations = true
64: end
Instructs the model to skip validations defined in superclasses
# File lib/sequel/plugins/validation_class_methods.rb, line 67
67: def skip_superclass_validations?
68: defined?(@skip_superclass_validations) && @skip_superclass_validations
69: end
Validates the given instance.
# File lib/sequel/plugins/validation_class_methods.rb, line 91
91: def validate(o)
92: superclass.validate(o) if superclass.respond_to?(:validate) && !skip_superclass_validations?
93: validations.each do |att, procs|
94: v = case att
95: when Array
96: att.collect{|a| o.send(a)}
97: else
98: o.send(att)
99: end
100: procs.each {|tag, p| p.call(o, att, v)}
101: end
102: end
Defines validations by converting a longhand block into a series of shorthand definitions. For example:
class MyClass < Sequel::Model
validates do
length_of :name, :minimum => 6
length_of :password, :minimum => 8
end
end
is equivalent to:
class MyClass < Sequel::Model
validates_length_of :name, :minimum => 6
validates_length_of :password, :minimum => 8
end
# File lib/sequel/plugins/validation_class_methods.rb, line 86
86: def validates(&block)
87: Generator.new(self, &block)
88: end
Validates acceptance of an attribute. Just checks that the value is equal to the :accept option. This method is unique in that :allow_nil is assumed to be true instead of false.
Possible Options:
# File lib/sequel/plugins/validation_class_methods.rb, line 111
111: def validates_acceptance_of(*atts)
112: opts = {
113: :message => 'is not accepted',
114: :allow_nil => true,
115: :accept => '1',
116: :tag => :acceptance,
117: }.merge!(extract_options!(atts))
118: atts << opts
119: validates_each(*atts) do |o, a, v|
120: o.errors.add(a, opts[:message]) unless v == opts[:accept]
121: end
122: end
Validates confirmation of an attribute. Checks that the object has a _confirmation value matching the current value. For example:
validates_confirmation_of :blah
Just makes sure that object.blah = object.blah_confirmation. Often used for passwords or email addresses on web forms.
Possible Options:
# File lib/sequel/plugins/validation_class_methods.rb, line 134
134: def validates_confirmation_of(*atts)
135: opts = {
136: :message => 'is not confirmed',
137: :tag => :confirmation,
138: }.merge!(extract_options!(atts))
139: atts << opts
140: validates_each(*atts) do |o, a, v|
141: o.errors.add(a, opts[:message]) unless v == o.send("#{a}_confirmation""#{a}_confirmation")
142: end
143: end
Adds a validation for each of the given attributes using the supplied block. The block must accept three arguments: instance, attribute and value, e.g.:
validates_each :name, :password do |object, attribute, value|
object.errors.add(attribute, 'is not nice') unless value.nice?
end
Possible Options:
# File lib/sequel/plugins/validation_class_methods.rb, line 168
168: def validates_each(*atts, &block)
169: opts = extract_options!(atts)
170: blk = if (i = opts[:if]) || (am = opts[:allow_missing]) || (an = opts[:allow_nil]) || (ab = opts[:allow_blank])
171: proc do |o,a,v|
172: next if i && !validation_if_proc(o, i)
173: next if an && Array(v).all?{|x| x.nil?}
174: next if ab && Array(v).all?{|x| x.blank?}
175: next if am && Array(a).all?{|x| !o.values.has_key?(x)}
176: block.call(o,a,v)
177: end
178: else
179: block
180: end
181: tag = opts[:tag]
182: atts.each do |a|
183: a_vals = @validation_mutex.synchronize{validations[a] ||= []}
184: if tag && (old = a_vals.find{|x| x[0] == tag})
185: old[1] = blk
186: else
187: a_vals << [tag, blk]
188: end
189: end
190: end
Validates the format of an attribute, checking the string representation of the value against the regular expression provided by the :with option.
Possible Options:
# File lib/sequel/plugins/validation_class_methods.rb, line 198
198: def validates_format_of(*atts)
199: opts = {
200: :message => 'is invalid',
201: :tag => :format,
202: }.merge!(extract_options!(atts))
203:
204: unless opts[:with].is_a?(Regexp)
205: raise ArgumentError, "A regular expression must be supplied as the :with option of the options hash"
206: end
207:
208: atts << opts
209: validates_each(*atts) do |o, a, v|
210: o.errors.add(a, opts[:message]) unless v.to_s =~ opts[:with]
211: end
212: end
Validates that an attribute is within a specified range or set of values.
Possible Options:
# File lib/sequel/plugins/validation_class_methods.rb, line 324
324: def validates_inclusion_of(*atts)
325: opts = extract_options!(atts)
326: unless opts[:in] && opts[:in].respond_to?(:include?)
327: raise ArgumentError, "The :in parameter is required, and respond to include?"
328: end
329: opts[:message] ||= "is not in range or set: #{opts[:in].inspect}"
330: atts << opts
331: validates_each(*atts) do |o, a, v|
332: o.errors.add(a, opts[:message]) unless opts[:in].include?(v)
333: end
334: end
Validates the length of an attribute.
Possible Options:
# File lib/sequel/plugins/validation_class_methods.rb, line 226
226: def validates_length_of(*atts)
227: opts = {
228: :too_long => 'is too long',
229: :too_short => 'is too short',
230: :wrong_length => 'is the wrong length'
231: }.merge!(extract_options!(atts))
232:
233: opts[:tag] ||= ([:length] + [:maximum, :minimum, :is, :within].reject{|x| !opts.include?(x)}).join('-').to_sym
234: atts << opts
235: validates_each(*atts) do |o, a, v|
236: if m = opts[:maximum]
237: o.errors.add(a, opts[:message] || opts[:too_long]) unless v && v.size <= m
238: end
239: if m = opts[:minimum]
240: o.errors.add(a, opts[:message] || opts[:too_short]) unless v && v.size >= m
241: end
242: if i = opts[:is]
243: o.errors.add(a, opts[:message] || opts[:wrong_length]) unless v && v.size == i
244: end
245: if w = opts[:within]
246: o.errors.add(a, opts[:message] || opts[:wrong_length]) unless v && w.include?(v.size)
247: end
248: end
249: end
Validates whether an attribute is not a string. This is generally useful in conjunction with raise_on_typecast_failure = false, where you are passing in string values for non-string attributes (such as numbers and dates). If typecasting fails (invalid number or date), the value of the attribute will be a string in an invalid format, and if typecasting succeeds, the value will not be a string.
Possible Options:
# File lib/sequel/plugins/validation_class_methods.rb, line 260
260: def validates_not_string(*atts)
261: opts = {
262: :tag => :not_string,
263: }.merge!(extract_options!(atts))
264: atts << opts
265: validates_each(*atts) do |o, a, v|
266: if v.is_a?(String)
267: unless message = opts[:message]
268: message = if sch = o.db_schema[a] and typ = sch[:type]
269: "is not a valid #{typ}"
270: else
271: "is a string"
272: end
273: end
274: o.errors.add(a, message)
275: end
276: end
277: end
Validates whether an attribute is a number.
Possible Options:
# File lib/sequel/plugins/validation_class_methods.rb, line 284
284: def validates_numericality_of(*atts)
285: opts = {
286: :message => 'is not a number',
287: :tag => :numericality,
288: }.merge!(extract_options!(atts))
289: atts << opts
290: validates_each(*atts) do |o, a, v|
291: begin
292: if opts[:only_integer]
293: Kernel.Integer(v.to_s)
294: else
295: Kernel.Float(v.to_s)
296: end
297: rescue
298: o.errors.add(a, opts[:message])
299: end
300: end
301: end
Validates the presence of an attribute. Requires the value not be blank, with false considered present instead of absent.
Possible Options:
# File lib/sequel/plugins/validation_class_methods.rb, line 308
308: def validates_presence_of(*atts)
309: opts = {
310: :message => 'is not present',
311: :tag => :presence,
312: }.merge!(extract_options!(atts))
313: atts << opts
314: validates_each(*atts) do |o, a, v|
315: o.errors.add(a, opts[:message]) if v.blank? && v != false
316: end
317: end
Validates only if the fields in the model (specified by atts) are unique in the database. Pass an array of fields instead of multiple fields to specify that the combination of fields must be unique, instead of that each field should have a unique value.
This means that the code:
validates_uniqueness_of([:column1, :column2])
validates the grouping of column1 and column2 while
validates_uniqueness_of(:column1, :column2)
validates them separately.
You should also add a unique index in the database, as this suffers from a fairly obvious race condition.
Possible Options:
# File lib/sequel/plugins/validation_class_methods.rb, line 352
352: def validates_uniqueness_of(*atts)
353: opts = {
354: :message => 'is already taken',
355: :tag => :uniqueness,
356: }.merge!(extract_options!(atts))
357:
358: atts << opts
359: validates_each(*atts) do |o, a, v|
360: error_field = a
361: a = Array(a)
362: v = Array(v)
363: ds = o.class.filter(a.zip(v))
364: num_dups = ds.count
365: allow = if num_dups == 0
366: # No unique value in the database
367: true
368: elsif num_dups > 1
369: # Multiple "unique" values in the database!!
370: # Someone didn't add a unique index
371: false
372: elsif o.new?
373: # New record, but unique value already exists in the database
374: false
375: elsif ds.first === o
376: # Unique value exists in database, but for the same record, so the update won't cause a duplicate record
377: true
378: else
379: false
380: end
381: o.errors.add(error_field, opts[:message]) unless allow
382: end
383: end