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 101 def validates_exact_length(exact, atts, opts=OPTS) 102 validatable_attributes_for_type(:exact_length, atts, opts){|a,v,m| validation_error_message(m, exact) if v.nil? || v.length != exact} 103 end
Check the string representation of the attribute value(s) against the regular expression with.
# File lib/sequel/plugins/validation_helpers.rb 106 def validates_format(with, atts, opts=OPTS) 107 validatable_attributes_for_type(:format, atts, opts){|a,v,m| validation_error_message(m, with) unless v.to_s =~ with} 108 end
Check attribute value(s) is included in the given set.
# File lib/sequel/plugins/validation_helpers.rb 111 def validates_includes(set, atts, opts=OPTS) 112 validatable_attributes_for_type(:includes, atts, opts){|a,v,m| validation_error_message(m, set) unless set.public_send(set.respond_to?(:cover?) ? :cover? : :include?, v)} 113 end
Check attribute value(s) string representation is a valid integer.
# File lib/sequel/plugins/validation_helpers.rb 116 def validates_integer(atts, opts=OPTS) 117 validatable_attributes_for_type(:integer, atts, opts) do |a,v,m| 118 begin 119 Kernel.Integer(v.to_s) 120 nil 121 rescue 122 validation_error_message(m) 123 end 124 end 125 end
Check that the attribute values length is in the specified range.
# File lib/sequel/plugins/validation_helpers.rb 128 def validates_length_range(range, atts, opts=OPTS) 129 validatable_attributes_for_type(:length_range, atts, opts){|a,v,m| validation_error_message(m, range) if v.nil? || !range.cover?(v.length)} 130 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 136 def validates_max_length(max, atts, opts=OPTS) 137 validatable_attributes_for_type(:max_length, atts, opts) do |a,v,m| 138 if v.nil? 139 validation_error_message(opts[:nil_message] || default_validation_helpers_options(:max_length)[:nil_message]) 140 elsif v.length > max 141 validation_error_message(m, max) 142 end 143 end 144 end
Check that the attribute values are not shorter than the given min length.
# File lib/sequel/plugins/validation_helpers.rb 147 def validates_min_length(min, atts, opts=OPTS) 148 validatable_attributes_for_type(:min_length, atts, opts){|a,v,m| validation_error_message(m, min) if v.nil? || v.length < min} 149 end
Check attribute value(s) are not NULL/nil.
# File lib/sequel/plugins/validation_helpers.rb 152 def validates_not_null(atts, opts=OPTS) 153 validatable_attributes_for_type(:not_null, atts, opts){|a,v,m| validation_error_message(m) if v.nil?} 154 end
Check attribute value(s) string representation is a valid float.
# File lib/sequel/plugins/validation_helpers.rb 157 def validates_numeric(atts, opts=OPTS) 158 validatable_attributes_for_type(:numeric, atts, opts) do |a,v,m| 159 begin 160 Kernel.Float(v.to_s) 161 nil 162 rescue 163 validation_error_message(m) 164 end 165 end 166 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 170 def validates_operator(operator, rhs, atts, opts=OPTS) 171 validatable_attributes_for_type(:operator, atts, opts){|a,v,m| validation_error_message(m, operator, rhs) if v.nil? || !v.public_send(operator, rhs)} 172 end
Check attribute value(s) is not considered blank by the database, but allow false values.
# File lib/sequel/plugins/validation_helpers.rb 197 def validates_presence(atts, opts=OPTS) 198 validatable_attributes_for_type(:presence, atts, opts){|a,v,m| validation_error_message(m) if model.db.send(:blank_object?, v) && v != false} 199 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 177 def validates_schema_types(atts=keys, opts=OPTS) 178 Array(atts).each do |k| 179 if type = schema_type_class(k) 180 validates_type(type, k, {:allow_nil=>true}.merge!(opts)) 181 end 182 end 183 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 187 def validates_type(klass, atts, opts=OPTS) 188 klass = klass.to_s.constantize if klass.is_a?(String) || klass.is_a?(Symbol) 189 validatable_attributes_for_type(:type, atts, opts) do |a,v,m| 190 if klass.is_a?(Array) ? !klass.any?{|kls| v.is_a?(kls)} : !v.is_a?(klass) 191 validation_error_message(m, klass) 192 end 193 end 194 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, true by default.
- :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:(lambda do |ds, obj, cols| ds.where(cols.map do |c| v = obj.public_send(c) v = v.downcase if v [Sequel.function(:lower, c), v] end) end)
# File lib/sequel/plugins/validation_helpers.rb 245 def validates_unique(*atts) 246 opts = default_validation_helpers_options(:unique) 247 if atts.last.is_a?(Hash) 248 opts = opts.merge(atts.pop) 249 end 250 message = validation_error_message(opts[:message]) 251 from_values = opts[:from] == :values 252 where = opts[:where] 253 atts.each do |a| 254 arr = Array(a) 255 next if arr.any?{|x| errors.on(x)} 256 cc = changed_columns 257 next if opts.fetch(:only_if_modified, true) && !new? && !arr.any?{|x| cc.include?(x)} 258 ds = opts[:dataset] || model.dataset 259 ds = if where 260 where.call(ds, self, arr) 261 else 262 vals = arr.map{|x| from_values ? values[x] : get_column_value(x)} 263 next if vals.any?(&:nil?) 264 ds.where(arr.zip(vals)) 265 end 266 ds = yield(ds) if block_given? 267 unless new? 268 h = ds.joined_dataset? ? qualified_pk_hash : pk_hash 269 ds = ds.exclude(h) 270 end 271 errors.add(a, message) unless ds.count == 0 272 end 273 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 281 def default_validation_helpers_options(type) 282 DEFAULT_OPTIONS[type] 283 end
Skip validating any attribute that matches one of the allow_* options, or already has an error if the skip_invalid option is given.
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 291 def validatable_attributes(atts, opts) 292 am, an, ab, m, si = opts.values_at(:allow_missing, :allow_nil, :allow_blank, :message, :skip_invalid) 293 from_values = opts[:from] == :values 294 Array(atts).each do |a| 295 next if si && errors.on(a) 296 next if am && !values.has_key?(a) 297 v = from_values ? values[a] : get_column_value(a) 298 next if an && v.nil? 299 next if ab && model.db.send(:blank_object?, v) 300 if message = yield(a, v, m) 301 errors.add(a, message) 302 end 303 end 304 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 308 def validatable_attributes_for_type(type, atts, opts, &block) 309 validatable_attributes(atts, default_validation_helpers_options(type).merge(opts), &block) 310 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 315 def validation_error_message(message, *args) 316 message.is_a?(Proc) ? message.call(*args) : message 317 end