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 = {}) ⇒ Object

Check that the attribute values are the given exact length.



95
96
97
# File 'lib/sequel/plugins/validation_helpers.rb', line 95

def validates_exact_length(exact, atts, opts={})
  validatable_attributes_for_type(:exact_length, atts, opts){|a,v,m| validation_error_message(m, exact) unless v && v.length == exact}
end

#validates_format(with, atts, opts = {}) ⇒ Object

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



100
101
102
# File 'lib/sequel/plugins/validation_helpers.rb', line 100

def validates_format(with, atts, 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 = {}) ⇒ Object

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



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

def validates_includes(set, atts, 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

#validates_integer(atts, opts = {}) ⇒ Object

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



110
111
112
113
114
115
116
117
118
119
# File 'lib/sequel/plugins/validation_helpers.rb', line 110

def validates_integer(atts, 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 = {}) ⇒ Object

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



122
123
124
# File 'lib/sequel/plugins/validation_helpers.rb', line 122

def validates_length_range(range, atts, opts={})
  validatable_attributes_for_type(:length_range, atts, opts){|a,v,m| validation_error_message(m, range) unless v && range.send(range.respond_to?(:cover?) ? :cover? : :include?, v.length)}
end

#validates_max_length(max, atts, 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.



130
131
132
# File 'lib/sequel/plugins/validation_helpers.rb', line 130

def validates_max_length(max, atts, 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]) unless v && v.length <= max}
end

#validates_min_length(min, atts, opts = {}) ⇒ Object

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



135
136
137
# File 'lib/sequel/plugins/validation_helpers.rb', line 135

def validates_min_length(min, atts, opts={})
  validatable_attributes_for_type(:min_length, atts, opts){|a,v,m| validation_error_message(m, min) unless v && v.length >= min}
end

#validates_not_string(atts, opts = {}) ⇒ Object

Check that the attribute value(s) 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.



145
146
147
# File 'lib/sequel/plugins/validation_helpers.rb', line 145

def validates_not_string(atts, opts={})
  validatable_attributes_for_type(:not_string, atts, opts){|a,v,m| validation_error_message(m, (db_schema[a]||{})[:type]) if v.is_a?(String)}
end

#validates_numeric(atts, opts = {}) ⇒ Object

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



150
151
152
153
154
155
156
157
158
159
# File 'lib/sequel/plugins/validation_helpers.rb', line 150

def validates_numeric(atts, 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_presence(atts, opts = {}) ⇒ Object

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



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

def validates_presence(atts, 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_type(klass, atts, opts = {}) ⇒ Object

Check if value is an instance of a class



162
163
164
165
# File 'lib/sequel/plugins/validation_helpers.rb', line 162

def validates_type(klass, atts, opts={})
  klass = klass.to_s.constantize if klass.is_a?(String) || klass.is_a?(Symbol)
  validatable_attributes_for_type(:type, atts, opts){|a,v,m| validation_error_message(m, klass) if v && !v.is_a?(klass)}
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.filter(: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:

: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 to a case insensitive uniqueness validation on a database that is case sensitive by default, you can use:

: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)


214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
# File 'lib/sequel/plugins/validation_helpers.rb', line 214

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])
  where = opts[:where]
  atts.each do |a|
    arr = Array(a)
    next if opts[:only_if_modified] && !new? && !arr.any?{|x| changed_columns.include?(x)}
    ds = if where
      where.call(model.dataset, self, arr)
    else
      vals = arr.map{|x| send(x)}
      next unless vals.all?
      model.where(arr.zip(vals))
    end
    ds = yield(ds) if block_given?
    ds = ds.exclude(pk_hash) unless new?
    errors.add(a, message) unless ds.count == 0
  end
end