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? errors.clear validate errors.empty? end
Base validate implementation. Override this method in subclasses.
# File lib/scrivener/validations.rb, line 77 def validate 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 221 def assert(value, error) value or errors[error.first].push(error.last) && false end
# File lib/scrivener/validations.rb, line 177 def assert_decimal(att, error = [att, :not_decimal]) assert_format att, DECIMAL, error end
# File lib/scrivener/validations.rb, line 154 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 198 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 164 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 160 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) value = send(att) if RUBY_ENGINE == 'opal' assert(value.respond_to?(:to_int) || value.to_s.match(/^\-?\d+$/), error) else assert(value.respond_to?(:to_int) || value.to_s.match(/\A\-?\d+\z/), error) end 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 138 def assert_url(att, error = [att, :not_url]) if assert_present(att, error) assert_format(att, URL, error) end end