Module Sequel::Plugins::ValidationClassMethods::ClassMethods
In: lib/sequel/plugins/validation_class_methods.rb

Methods

Classes and Modules

Class Sequel::Plugins::ValidationClassMethods::ClassMethods::Generator

Attributes

validation_reflections  [R]  A hash of validation reflections for this model class. Keys are column symbols, values are an array of two element arrays, with the first element being the validation type symbol and the second being a hash of validation options.
validations  [R]  A hash of validations for this model class. Keys are column symbols, values are arrays of validation procs.

Public Instance methods

Freeze validation metadata when freezing model class.

[Source]

    # File lib/sequel/plugins/validation_class_methods.rb, line 41
41:         def freeze
42:           @validations.freeze.each_value(&:freeze)
43:           @validation_reflections.freeze.each_value do |vs|
44:             vs.freeze.each do |v|
45:               v.freeze
46:               v.last.freeze
47:             end
48:           end
49: 
50:           super
51:         end

Returns true if validations are defined.

[Source]

    # File lib/sequel/plugins/validation_class_methods.rb, line 74
74:         def has_validations?
75:           !validations.empty?
76:         end

Instructs the model to skip validations defined in superclasses

[Source]

    # File lib/sequel/plugins/validation_class_methods.rb, line 81
81:         def skip_superclass_validations
82:           superclass.validations.each do |att, procs|
83:             if @validations[att]
84:               @validations[att] -= procs
85:             end
86:           end
87:           @skip_superclass_validations = true
88:         end

Instructs the model to skip validations defined in superclasses

[Source]

    # File lib/sequel/plugins/validation_class_methods.rb, line 91
91:         def skip_superclass_validations?
92:           @skip_superclass_validations
93:         end

Validates the given instance.

[Source]

     # File lib/sequel/plugins/validation_class_methods.rb, line 116
116:         def validate(o)
117:           validations.each do |att, procs|
118:             v = case att
119:             when Array
120:               att.map{|a| o.get_column_value(a)}
121:             else
122:               o.get_column_value(att)
123:             end
124:             procs.each {|tag, p| p.call(o, att, v)}
125:           end
126:         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

[Source]

     # File lib/sequel/plugins/validation_class_methods.rb, line 111
111:         def validates(&block)
112:           Generator.new(self, &block)
113:         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:

:accept :The value required for the object to be valid (default: ‘1’)
:message :The message to use (default: ‘is not accepted’)

[Source]

     # File lib/sequel/plugins/validation_class_methods.rb, line 135
135:         def validates_acceptance_of(*atts)
136:           opts = {
137:             :message => 'is not accepted',
138:             :allow_nil => true,
139:             :accept => '1',
140:             :tag => :acceptance,
141:           }.merge!(extract_options!(atts))
142:           reflect_validation(:acceptance, opts, atts)
143:           atts << opts
144:           validates_each(*atts) do |o, a, v|
145:             o.errors.add(a, opts[:message]) unless v == opts[:accept]
146:           end
147:         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:

:message :The message to use (default: ‘is not confirmed’)

[Source]

     # File lib/sequel/plugins/validation_class_methods.rb, line 159
159:         def validates_confirmation_of(*atts)
160:           opts = {
161:             :message => 'is not confirmed',
162:             :tag => :confirmation,
163:           }.merge!(extract_options!(atts))
164:           reflect_validation(:confirmation, opts, atts)
165:           atts << opts
166:           validates_each(*atts) do |o, a, v|
167:             o.errors.add(a, opts[:message]) unless v == o.get_column_value("#{a}_confirmation""#{a}_confirmation")
168:           end
169:         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:

:allow_blank :Whether to skip the validation if the value is blank.
:allow_missing :Whether to skip the validation if the attribute isn‘t a key in the values hash. This is different from allow_nil, because Sequel only sends the attributes in the values when doing an insert or update. If the attribute is not present, Sequel doesn‘t specify it, so the database will use the table‘s default value. This is different from having an attribute in values with a value of nil, which Sequel will send as NULL. If your database table has a non NULL default, this may be a good option to use. You don‘t want to use allow_nil, because if the attribute is in values but has a value nil, Sequel will attempt to insert a NULL value into the database, instead of using the database‘s default.
:allow_nil :Whether to skip the validation if the value is nil.
:if :A symbol (indicating an instance_method) or proc (which is instance_execed) skipping this validation if it returns nil or false.
:tag :The tag to use for this validation.

[Source]

     # File lib/sequel/plugins/validation_class_methods.rb, line 194
194:         def validates_each(*atts, &block)
195:           opts = extract_options!(atts)
196:           blank_meth = db.method(:blank_object?).to_proc
197:           blk = if (i = opts[:if]) || (am = opts[:allow_missing]) || (an = opts[:allow_nil]) || (ab = opts[:allow_blank])
198:             proc do |o,a,v|
199:               next if i && !validation_if_proc(o, i)
200:               next if an && Array(v).all?(&:nil?)
201:               next if ab && Array(v).all?(&blank_meth)
202:               next if am && Array(a).all?{|x| !o.values.has_key?(x)}
203:               block.call(o,a,v)
204:             end
205:           else
206:             block
207:           end
208:           tag = opts[:tag]
209:           atts.each do |a| 
210:             a_vals = Sequel.synchronize{validations[a] ||= []}
211:             if tag && (old = a_vals.find{|x| x[0] == tag})
212:               old[1] = blk
213:             else
214:               a_vals << [tag, blk]
215:             end
216:           end
217:         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:

:message :The message to use (default: ‘is invalid’)
:with :The regular expression to validate the value with (required).

[Source]

     # File lib/sequel/plugins/validation_class_methods.rb, line 225
225:         def validates_format_of(*atts)
226:           opts = {
227:             :message => 'is invalid',
228:             :tag => :format,
229:           }.merge!(extract_options!(atts))
230:           
231:           unless opts[:with].is_a?(Regexp)
232:             raise ArgumentError, "A regular expression must be supplied as the :with option of the options hash"
233:           end
234:           
235:           reflect_validation(:format, opts, atts)
236:           atts << opts
237:           validates_each(*atts) do |o, a, v|
238:             o.errors.add(a, opts[:message]) unless v.to_s =~ opts[:with]
239:           end
240:         end

Validates that an attribute is within a specified range or set of values.

Possible Options:

:in :An array or range of values to check for validity (required)
:message :The message to use (default: ‘is not in range or set: <specified range>’)

[Source]

     # File lib/sequel/plugins/validation_class_methods.rb, line 329
329:         def validates_inclusion_of(*atts)
330:           opts = extract_options!(atts)
331:           n = opts[:in]
332:           unless n && (n.respond_to?(:cover?) || n.respond_to?(:include?))
333:             raise ArgumentError, "The :in parameter is required, and must respond to cover? or include?"
334:           end
335:           opts[:message] ||= "is not in range or set: #{n.inspect}"
336:           reflect_validation(:inclusion, opts, atts)
337:           atts << opts
338:           validates_each(*atts) do |o, a, v|
339:             o.errors.add(a, opts[:message]) unless n.public_send(n.respond_to?(:cover?) ? :cover? : :include?, v)
340:           end
341:         end

Validates the length of an attribute.

Possible Options:

:is :The exact size required for the value to be valid (no default)
:maximum :The maximum size allowed for the value (no default)
:message :The message to use (no default, overrides :nil_message, :too_long, :too_short, and :wrong_length options if present)
:minimum :The minimum size allowed for the value (no default)
:nil_message :The message to use use if :maximum option is used and the value is nil (default: ‘is not present’)
:too_long :The message to use use if it the value is too long (default: ‘is too long’)
:too_short :The message to use use if it the value is too short (default: ‘is too short’)
:within :The array/range that must include the size of the value for it to be valid (no default)
:wrong_length :The message to use use if it the value is not valid (default: ‘is the wrong length’)

[Source]

     # File lib/sequel/plugins/validation_class_methods.rb, line 255
255:         def validates_length_of(*atts)
256:           opts = {
257:             :nil_message  => 'is not present',
258:             :too_long     => 'is too long',
259:             :too_short    => 'is too short',
260:             :wrong_length => 'is the wrong length'
261:           }.merge!(extract_options!(atts))
262:           
263:           opts[:tag] ||= ([:length] + [:maximum, :minimum, :is, :within].reject{|x| !opts.include?(x)}).join('-').to_sym
264:           reflect_validation(:length, opts, atts)
265:           atts << opts
266:           validates_each(*atts) do |o, a, v|
267:             if m = opts[:maximum]
268:               o.errors.add(a, opts[:message] || (v ? opts[:too_long] : opts[:nil_message])) unless v && v.size <= m
269:             end
270:             if m = opts[:minimum]
271:               o.errors.add(a, opts[:message] || opts[:too_short]) unless v && v.size >= m
272:             end
273:             if i = opts[:is]
274:               o.errors.add(a, opts[:message] || opts[:wrong_length]) unless v && v.size == i
275:             end
276:             if w = opts[:within]
277:               o.errors.add(a, opts[:message] || opts[:wrong_length]) unless v && w.public_send(w.respond_to?(:cover?) ? :cover? : :include?, v.size)
278:             end
279:           end
280:         end

Validates whether an attribute is a number.

Possible Options:

:message :The message to use (default: ‘is not a number’)
:only_integer :Whether only integers are valid values (default: false)

[Source]

     # File lib/sequel/plugins/validation_class_methods.rb, line 287
287:         def validates_numericality_of(*atts)
288:           opts = {
289:             :message => 'is not a number',
290:             :tag => :numericality,
291:           }.merge!(extract_options!(atts))
292:           reflect_validation(:numericality, opts, atts)
293:           atts << opts
294:           validates_each(*atts) do |o, a, v|
295:             begin
296:               if opts[:only_integer]
297:                 Kernel.Integer(v.to_s)
298:               else
299:                 Kernel.Float(v.to_s)
300:               end
301:             rescue
302:               o.errors.add(a, opts[:message])
303:             end
304:           end
305:         end

Validates the presence of an attribute. Requires the value not be blank, with false considered present instead of absent.

Possible Options:

:message :The message to use (default: ‘is not present’)

[Source]

     # File lib/sequel/plugins/validation_class_methods.rb, line 312
312:         def validates_presence_of(*atts)
313:           opts = {
314:             :message => 'is not present',
315:             :tag => :presence,
316:           }.merge!(extract_options!(atts))
317:           reflect_validation(:presence, opts, atts)
318:           atts << opts
319:           validates_each(*atts) do |o, a, v|
320:             o.errors.add(a, opts[:message]) if db.send(:blank_object?, v) && v != false
321:           end
322:         end

Validates whether an attribute has the correct ruby type for the associated database type. This is generally useful in conjunction with raise_on_typecast_failure = false, to handle typecasting errors at validation time instead of at setter time.

Possible Options:

:message :The message to use (default: ‘is not a valid (integer|datetime|etc.)’)

[Source]

     # File lib/sequel/plugins/validation_class_methods.rb, line 350
350:         def validates_schema_type(*atts)
351:           opts = {
352:             :tag => :schema_type,
353:           }.merge!(extract_options!(atts))
354:           reflect_validation(:schema_type, opts, atts)
355:           atts << opts
356:           validates_each(*atts) do |o, a, v|
357:             next if v.nil? || (klass = o.send(:schema_type_class, a)).nil?
358:             if klass.is_a?(Array) ? !klass.any?{|kls| v.is_a?(kls)} : !v.is_a?(klass)
359:               message = opts[:message] || "is not a valid #{Array(klass).join(" or ").downcase}"
360:               o.errors.add(a, message)
361:             end
362:           end
363:         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:

:message :The message to use (default: ‘is already taken’)

[Source]

     # File lib/sequel/plugins/validation_class_methods.rb, line 381
381:         def validates_uniqueness_of(*atts)
382:           opts = {
383:             :message => 'is already taken',
384:             :tag => :uniqueness,
385:           }.merge!(extract_options!(atts))
386:     
387:           reflect_validation(:uniqueness, opts, atts)
388:           atts << opts
389:           validates_each(*atts) do |o, a, v|
390:             error_field = a
391:             a = Array(a)
392:             v = Array(v)
393:             next if v.empty? || !v.all?
394:             ds = o.class.where(a.zip(v))
395:             num_dups = ds.count
396:             allow = if num_dups == 0
397:               # No unique value in the database
398:               true
399:             elsif num_dups > 1
400:               # Multiple "unique" values in the database!!
401:               # Someone didn't add a unique index
402:               false
403:             elsif o.new?
404:               # New record, but unique value already exists in the database
405:               false
406:             elsif ds.first === o
407:               # Unique value exists in database, but for the same record, so the update won't cause a duplicate record
408:               true
409:             else
410:               false
411:             end
412:             o.errors.add(error_field, opts[:message]) unless allow
413:           end
414:         end

[Validate]