module Scrivener::Validations
Provides a base implementation for extensible validation routines. {Scrivener::Validations} currently only provides the following assertions:
-
assert
The core tenets that Scrivener::Validations
advocates can be summed up in a few bullet points:
-
Validations
are much simpler and better done using composition rather than macros. -
Error messages should be kept separate and possibly in the view or presenter layer.
-
It should be easy to write your own validation routine.
Other validations are simply added on a per-model or per-project basis.
@example
class Quote attr_accessor :title attr_accessor :price attr_accessor :date def validate assert_present :title assert_numeric :price assert_format :date, /\A[\d]{4}-[\d]{1,2}-[\d]{1,2}\z end end s = Quote.new s.valid? # => false s.errors # => { :title => [:not_present], :price => [:not_numeric], :date => [:format] }
Constants
- DECIMAL
- URL
Public Instance Methods
Hash of errors for each attribute in this model.
# File lib/scrivener/validations.rb, line 81 def errors @errors ||= Hash.new { |hash, key| hash[key] = [] } end
Check if the current model state is valid. Each call to {#valid?} will reset the {#errors} array.
All validations should be declared in a `validate` method.
@example
class Login attr_accessor :username attr_accessor :password def validate assert_present :user assert_present :password end end
# File lib/scrivener/validations.rb, line 70 def valid?(*args, **kargs) errors.clear validate(*args, **kargs) errors.empty? end
Base validate implementation. Override this method in subclasses.
# File lib/scrivener/validations.rb, line 77 def validate(*args, **kargs) end
Protected Instance Methods
The grand daddy of all assertions. If you want to build custom assertions, or even quick and dirty ones, you can simply use this method.
@example
class CreatePost attr_accessor :slug attr_accessor :votes def validate assert_slug :slug assert votes.to_i > 0, [:votes, :not_valid] end protected def assert_slug(att, error = [att, :not_slug]) assert send(att).to_s =~ /\A[a-z\-0-9]+\z/, error end end
# File lib/scrivener/validations.rb, line 202 def assert(value, error) value or errors[error.first].push(error.last) && false end
# File lib/scrivener/validations.rb, line 158 def assert_decimal(att, error = [att, :not_decimal]) assert_format att, DECIMAL, error end
# File lib/scrivener/validations.rb, line 139 def assert_email(att, error = [att, :not_email]) if assert_present(att, error) assert_format(att, EMAIL, error) end end
Check that the attribute has the expected value. It uses === for comparison, so type checks are possible too. Note that in order to make the case equality work, the check inverts the order of the arguments: `assert_equal :foo, Bar` is translated to the expression `Bar === send(:foo)`.
@example
def validate assert_equal :status, "pending" assert_equal :quantity, Fixnum end
@param [Symbol] att The attribute you wish to verify for equality. @param [Object] value The value you want to test against. @param [Array<Symbol, Symbol>] error The error that should be returned
when the validation fails.
# File lib/scrivener/validations.rb, line 179 def assert_equal(att, value, error = [att, :not_equal]) assert value === send(att), error end
Allows you to do a validation check against a regular expression. It's important to note that this internally calls {#assert_present}, therefore you need not structure your regular expression to check for a non-empty value.
@param [Symbol] att The attribute you want to verify the format of. @param [Regexp] format The regular expression with which to compare
the value of att with.
@param [Array<Symbol, Symbol>] error The error that should be returned
when the validation fails.
# File lib/scrivener/validations.rb, line 97 def assert_format(att, format, error = [att, :format]) if assert_present(att, error) assert(send(att).to_s.match(format), error) end end
# File lib/scrivener/validations.rb, line 149 def assert_length(att, range, error = [att, :not_in_range]) if assert_present(att, error) val = send(att).to_s assert range.include?(val.length), error end end
# File lib/scrivener/validations.rb, line 145 def assert_member(att, set, err = [att, :not_valid]) assert(set.include?(send(att)), err) end
Checks if all the characters of an attribute is a digit.
@param [Symbol] att The attribute you wish to verify the numeric format. @param [Array<Symbol, Symbol>] error The error that should be returned
when the validation fails.
# File lib/scrivener/validations.rb, line 118 def assert_numeric(att, error = [att, :not_numeric]) if assert_present(att, error) assert_format(att, /\A\-?\d+\z/, error) end end
The most basic and highly useful assertion. Simply checks if the value of the attribute is empty.
@param [Symbol] att The attribute you wish to verify the presence of. @param [Array<Symbol, Symbol>] error The error that should be returned
when the validation fails.
# File lib/scrivener/validations.rb, line 109 def assert_present(att, error = [att, :not_present]) assert(!send(att).to_s.empty?, error) end
# File lib/scrivener/validations.rb, line 128 def assert_url(att, error = [att, :not_url]) if assert_present(att, error) assert_format(att, URL, error) end end