module Sequel::Plugins::ValidationHelpers::InstanceMethods
Public Instance Methods
Check that the attribute values are the given exact length.
# File lib/sequel/plugins/validation_helpers.rb, line 98 def validates_exact_length(exact, atts, opts=OPTS) validatable_attributes_for_type(:exact_length, atts, opts){|a,v,m| validation_error_message(m, exact) if v.nil? || v.length != exact} end
Check the string representation of the attribute value(s) against the regular expression with.
# File lib/sequel/plugins/validation_helpers.rb, line 103 def validates_format(with, atts, opts=OPTS) validatable_attributes_for_type(:format, atts, opts){|a,v,m| validation_error_message(m, with) unless v.to_s =~ with} end
Check attribute value(s) is included in the given set.
# File lib/sequel/plugins/validation_helpers.rb, line 108 def validates_includes(set, atts, opts=OPTS) validatable_attributes_for_type(:includes, atts, opts){|a,v,m| validation_error_message(m, set) unless set.send(set.respond_to?(:cover?) ? :cover? : :include?, v)} end
Check attribute value(s) string representation is a valid integer.
# File lib/sequel/plugins/validation_helpers.rb, line 113 def validates_integer(atts, opts=OPTS) validatable_attributes_for_type(:integer, atts, opts) do |a,v,m| begin Kernel.Integer(v.to_s) nil rescue validation_error_message(m) end end end
Check that the attribute values length is in the specified range.
# File lib/sequel/plugins/validation_helpers.rb, line 125 def validates_length_range(range, atts, opts=OPTS) validatable_attributes_for_type(:length_range, atts, opts){|a,v,m| validation_error_message(m, range) if v.nil? || !range.send(range.respond_to?(:cover?) ? :cover? : :include?, v.length)} end
Check that the attribute values are not longer than the given max length.
Accepts a :nil_message option that is the error message to use when the value is nil instead of being too long.
# File lib/sequel/plugins/validation_helpers.rb, line 133 def validates_max_length(max, atts, opts=OPTS) validatable_attributes_for_type(:max_length, atts, opts){|a,v,m| v ? validation_error_message(m, max) : validation_error_message(opts[:nil_message] || DEFAULT_OPTIONS[:max_length][:nil_message]) if v.nil? || v.length > max} end
Check that the attribute values are not shorter than the given min length.
# File lib/sequel/plugins/validation_helpers.rb, line 138 def validates_min_length(min, atts, opts=OPTS) validatable_attributes_for_type(:min_length, atts, opts){|a,v,m| validation_error_message(m, min) if v.nil? || v.length < min} end
Check attribute value(s) are not NULL/nil.
# File lib/sequel/plugins/validation_helpers.rb, line 143 def validates_not_null(atts, opts=OPTS) validatable_attributes_for_type(:not_null, atts, opts){|a,v,m| validation_error_message(m) if v.nil?} end
Check attribute value(s) string representation is a valid float.
# File lib/sequel/plugins/validation_helpers.rb, line 148 def validates_numeric(atts, opts=OPTS) validatable_attributes_for_type(:numeric, atts, opts) do |a,v,m| begin Kernel.Float(v.to_s) nil rescue validation_error_message(m) end end end
Check attribute value(s) against a specified value and operation, e.g. #validates_operator(:>, 3, :value) validates that value > 3.
# File lib/sequel/plugins/validation_helpers.rb, line 161 def validates_operator(operator, rhs, atts, opts=OPTS) validatable_attributes_for_type(:operator, atts, opts){|a,v,m| validation_error_message(m, operator, rhs) if v.nil? || !v.send(operator, rhs)} end
Check attribute value(s) is not considered blank by the database, but allow false values.
# File lib/sequel/plugins/validation_helpers.rb, line 188 def validates_presence(atts, opts=OPTS) validatable_attributes_for_type(:presence, atts, opts){|a,v,m| validation_error_message(m) if model.db.send(:blank_object?, v) && v != false} end
Validates for all of the model columns (or just the given columns) that the column value is an instance of the expected class based on the column's schema type.
# File lib/sequel/plugins/validation_helpers.rb, line 168 def validates_schema_types(atts=keys, opts=OPTS) Array(atts).each do |k| if type = schema_type_class(k) validates_type(type, k, {:allow_nil=>true}.merge!(opts)) end end end
Check if value is an instance of a class. If klass
is an
array, the value must be an instance of one of the classes in the array.
# File lib/sequel/plugins/validation_helpers.rb, line 178 def validates_type(klass, atts, opts=OPTS) klass = klass.to_s.constantize if klass.is_a?(String) || klass.is_a?(Symbol) validatable_attributes_for_type(:type, atts, opts) do |a,v,m| if klass.is_a?(Array) ? !klass.any?{|kls| v.is_a?(kls)} : !v.is_a?(klass) validation_error_message(m, klass) end end end
Checks that there are no duplicate values in the database for the given attributes. 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_unique([:column1, :column2])
validates the grouping of column1 and column2 while
validates_unique(:column1, :column2)
validates them separately.
You can pass a block, which is yielded the dataset in which the columns must be unique. So if you are doing a soft delete of records, in which the name must be unique, but only for active records:
validates_unique(:name){|ds| ds.where(:active)}
You should also add a unique index in the database, as this suffers from a fairly obvious race condition.
This validation does not respect the :allow_* options that the other validations accept, since it can deal with a grouping of multiple attributes.
Possible Options:
- :dataset
-
The base dataset to use for the unique query, defaults to the model's dataset.
- :message
-
The message to use (default: 'is already taken')
- :only_if_modified
-
Only check the uniqueness if the object is new or one of the columns has been modified.
- :where
-
A callable object where call takes three arguments, a dataset, the current object, and an array of columns, and should return a modified dataset that is filtered to include only rows with the same values as the current object for each column in the array.
If you want to do a case insensitive uniqueness validation on a database that is case sensitive by default, you can use:
validates_unique :column, :where=>(proc do |ds, obj, cols| ds.where(cols.map do |c| v = obj.send(c) v = v.downcase if v [Sequel.function(:lower, c), v] end) end)
# File lib/sequel/plugins/validation_helpers.rb, line 236 def validates_unique(*atts) opts = default_validation_helpers_options(:unique) if atts.last.is_a?(Hash) opts = Hash[opts].merge!(atts.pop) end message = validation_error_message(opts[:message]) from_values = opts[:from] == :values where = opts[:where] atts.each do |a| arr = Array(a) next if arr.any?{|x| errors.on(x)} # SEQUEL5: Default only_if_modified to true next if opts[:only_if_modified] && !new? && !arr.any?{|x| changed_columns.include?(x)} ds = opts[:dataset] || model.dataset ds = if where where.call(ds, self, arr) else vals = arr.map{|x| from_values ? values[x] : get_column_value(x)} next if vals.any?(&:nil?) ds.where(arr.zip(vals)) end ds = yield(ds) if block_given? unless new? h = ds.joined_dataset? ? qualified_pk_hash : pk_hash ds = ds.exclude(h) end errors.add(a, message) unless ds.count == 0 end end
Private Instance Methods
The default options hash for the given type of validation. Can be overridden on a per-model basis for different per model defaults. The hash return must include a :message option that is either a proc or string.
# File lib/sequel/plugins/validation_helpers.rb, line 272 def default_validation_helpers_options(type) DEFAULT_OPTIONS[type] end
Skip validating any attribute that matches one of the allow_* options. Otherwise, yield the attribute, value, and passed option :message to the block. If the block returns anything except nil or false, add it as an error message for that attributes.
# File lib/sequel/plugins/validation_helpers.rb, line 280 def validatable_attributes(atts, opts) am, an, ab, m = opts.values_at(:allow_missing, :allow_nil, :allow_blank, :message) from_values = opts[:from] == :values Array(atts).each do |a| next if am && !values.has_key?(a) v = from_values ? values[a] : get_column_value(a) next if an && v.nil? next if ab && v.respond_to?(:blank?) && v.blank? if message = yield(a, v, m) errors.add(a, message) end end end
Merge the given options with the default options for the given type and call #validatable_attributes with the merged options.
# File lib/sequel/plugins/validation_helpers.rb, line 296 def validatable_attributes_for_type(type, atts, opts, &block) validatable_attributes(atts, Hash[default_validation_helpers_options(type)].merge!(opts), &block) end
The validation error message to use, as a string. If message is a Proc, call it with the args. Otherwise, assume it is a string and return it.
# File lib/sequel/plugins/validation_helpers.rb, line 303 def validation_error_message(message, *args) message.is_a?(Proc) ? message.call(*args) : message end