Module: Sequel::Plugins::ValidationHelpers::InstanceMethods

Defined in:
lib/sequel/plugins/validation_helpers.rb

Instance Method Summary collapse

Instance Method Details

#validates_exact_length(exact, atts, opts = OPTS) ⇒ Object

Check that the attribute values are the given exact length.



105
106
107
# File 'lib/sequel/plugins/validation_helpers.rb', line 105

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

#validates_format(with, atts, opts = OPTS) ⇒ Object

Check the string representation of the attribute value(s) against the regular expression with.



110
111
112
# File 'lib/sequel/plugins/validation_helpers.rb', line 110

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

#validates_includes(set, atts, opts = OPTS) ⇒ Object

Check attribute value(s) is included in the given set.



115
116
117
# File 'lib/sequel/plugins/validation_helpers.rb', line 115

def validates_includes(set, atts, opts=OPTS)
  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)}
end

#validates_integer(atts, opts = OPTS) ⇒ Object

Check attribute value(s) string representation is a valid integer.



120
121
122
123
124
125
126
127
128
129
# File 'lib/sequel/plugins/validation_helpers.rb', line 120

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

#validates_length_range(range, atts, opts = OPTS) ⇒ Object

Check that the attribute values length is in the specified range.



132
133
134
# File 'lib/sequel/plugins/validation_helpers.rb', line 132

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.cover?(v.length)}
end

#validates_max_length(max, atts, opts = OPTS) ⇒ Object

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.



140
141
142
143
144
145
146
147
148
# File 'lib/sequel/plugins/validation_helpers.rb', line 140

def validates_max_length(max, atts, opts=OPTS)
  validatable_attributes_for_type(:max_length, atts, opts) do |a,v,m|
    if v.nil?
      validation_error_message(opts[:nil_message] || default_validation_helpers_options(:max_length)[:nil_message])
    elsif v.length > max
      validation_error_message(m, max)
    end
  end
end

#validates_max_value(max, atts, opts = OPTS) ⇒ Object

Check that the attribute values are not greater that the given maximum value. Does not perform validation if attribute value is nil. You should only call this if you have checked the attribute value has the expected type.



153
154
155
156
157
# File 'lib/sequel/plugins/validation_helpers.rb', line 153

def validates_max_value(max, atts, opts=OPTS)
  validatable_attributes_for_type(:max_value, atts, opts) do |a,v,m|
    validation_error_message(m, max) if !v.nil? && v > max
  end
end

#validates_min_length(min, atts, opts = OPTS) ⇒ Object

Check that the attribute values are not shorter than the given min length.



160
161
162
# File 'lib/sequel/plugins/validation_helpers.rb', line 160

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

#validates_min_value(min, atts, opts = OPTS) ⇒ Object

Check that the attribute values are not less that the given minimum value. Does not perform validation if attribute value is nil. You should only call this if you have checked the attribute value has the expected type.



167
168
169
170
171
# File 'lib/sequel/plugins/validation_helpers.rb', line 167

def validates_min_value(min, atts, opts=OPTS)
  validatable_attributes_for_type(:min_value, atts, opts) do |a,v,m|
    validation_error_message(m, min) if !v.nil? && v < min
  end
end

#validates_no_null_byte(atts, opts = OPTS) ⇒ Object

Check attribute value(s) does not contain a null (“0”, ASCII NUL) byte.



179
180
181
# File 'lib/sequel/plugins/validation_helpers.rb', line 179

def validates_no_null_byte(atts, opts=OPTS)
  validatable_attributes_for_type(:no_null_byte, atts, opts){|a,v,m| validation_error_message(m) if String === v && v.include?("\0")}
end

#validates_not_null(atts, opts = OPTS) ⇒ Object

Check attribute value(s) are not NULL/nil.



174
175
176
# File 'lib/sequel/plugins/validation_helpers.rb', line 174

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

#validates_numeric(atts, opts = OPTS) ⇒ Object

Check attribute value(s) string representation is a valid float.



184
185
186
187
188
189
190
191
192
193
# File 'lib/sequel/plugins/validation_helpers.rb', line 184

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

#validates_operator(operator, rhs, atts, opts = OPTS) ⇒ Object

Check attribute value(s) against a specified value and operation, e.g. validates_operator(:>, 3, :value) validates that value > 3.



197
198
199
# File 'lib/sequel/plugins/validation_helpers.rb', line 197

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.public_send(operator, rhs)}
end

#validates_presence(atts, opts = OPTS) ⇒ Object

Check attribute value(s) is not considered blank by the database, but allow false values.



224
225
226
# File 'lib/sequel/plugins/validation_helpers.rb', line 224

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_schema_types(atts = keys, opts = OPTS) ⇒ Object

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.



204
205
206
207
208
209
210
# File 'lib/sequel/plugins/validation_helpers.rb', line 204

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

#validates_type(klass, atts, opts = OPTS) ⇒ Object

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.



214
215
216
217
218
219
220
221
# File 'lib/sequel/plugins/validation_helpers.rb', line 214

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)
      validates_type_error_message(m, klass)
    end
  end
end

#validates_unique(*atts) ⇒ Object

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)


272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
# File 'lib/sequel/plugins/validation_helpers.rb', line 272

def validates_unique(*atts)
  opts = default_validation_helpers_options(:unique)
  if atts.last.is_a?(Hash)
    opts = 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)}
    cc = changed_columns
    next if opts.fetch(:only_if_modified, true) && !new? && !arr.any?{|x| cc.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 defined?(yield)
    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