valid-1.2.0/0000755000004100000410000000000013314620175012643 5ustar www-datawww-datavalid-1.2.0/README.md0000644000004100000410000000633513314620175014131 0ustar www-datawww-data# Validator [![Build Status](https://secure.travis-ci.org/zombor/Validator.png)](http://travis-ci.org/zombor/Validator) Validator is a simple ruby validation class. You don't use it directly inside your classes like just about every other ruby validation class out there. I chose to implement it in this way so I didn't automatically pollute the namespace of the objects I wanted to validate. This also solves the problem of validating forms very nicely. Frequently you will have a form that represents many different data objects in your system, and you can pre-validate everything before doing any saving. ## Usage Validator is useful for validating the state of any existing ruby object. ```ruby object = OpenStruct.new(:email => 'foo@bar.com', :password => 'foobar') validator = Validation::Validator.new(object) validator.rule(:email, [:email, :not_empty]) # multiple rules in one line validator.rule(:password, :not_empty) # a single rule on a line validator.rule(:password, :length => { :minimum => 3 }) # a rule that takes parameters if validator.valid? # save the data somewhere else @errors = validator.errors end ``` The first paramater can be any message that the object responds to. ### Writing your own rules If you have a custom rule you need to write, you can create a custom rule class for it: ```ruby class MyCustomRule def error_key :my_custom_rule end def valid_value?(value) # Logic for determining the validity of the value end def params {} end end ``` A rule class should have the following methods on it: - `error_key` a symbol to represent the error. This shows up in the errors hash. Must be an underscored_version of the class name - `valid_value?(value)` the beef of the rule. This is where you determine if the value is valid or not - `params` the params hash that was passed into the constructor If you add your custom rule class to the `Validation::Rule` namespace, you can reference it using a symbol: ```ruby validator.rule(:field, :my_custom_rule) # resolves to Validation::Rule::MyCustomRule validator.rule(:field, :my_custom_rule => { :param => :value }) ``` Otherwise, just pass in the rule class itself: ```ruby validator.rule(:field, MyProject::CustomRule) validator.rule(:field, MyProject::CustomRule => { :param => :value }) ``` ### Writing self-contained validators You can also create self-contained validation classes if you don't like the dynamic creation approach: ```ruby require 'validation' require 'validation/rule/not_empty' class MyFormValidator < Validation::Validator include Validation rule :email, :not_empty end ``` Now you can use this anywhere in your code: ```ruby form_validator = MyFormValidator.new(OpenStruct.new(params)) form_validator.valid? ``` # Semantic Versioning This project conforms to [semver](http://semver.org/). # Contributing Have an improvement? Have an awesome rule you want included? Simple! 1. Fork the repository 2. Create a branch off of the `master` branch 3. Write specs for the change 4. Add your change 5. Submit a pull request to merge against the `master` branch Don't change any version files or gemspec files in your change. valid-1.2.0/valid.gemspec0000644000004100000410000000237713314620175015320 0ustar www-datawww-data######################################################### # This file has been automatically generated by gem2tgz # ######################################################### # -*- encoding: utf-8 -*- # stub: valid 1.2.0 ruby lib Gem::Specification.new do |s| s.name = "valid".freeze s.version = "1.2.0" s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version= s.require_paths = ["lib".freeze] s.authors = ["Jeremy Bush".freeze] s.date = "2016-06-27" s.email = ["contractfrombelow@gmail.com".freeze] s.files = ["README.md".freeze, "lib/validation.rb".freeze, "lib/validation/rule/email.rb".freeze, "lib/validation/rule/length.rb".freeze, "lib/validation/rule/matches.rb".freeze, "lib/validation/rule/not_empty.rb".freeze, "lib/validation/rule/numeric.rb".freeze, "lib/validation/rule/phone.rb".freeze, "lib/validation/rule/regular_expression.rb".freeze, "lib/validation/rule/uri.rb".freeze, "lib/validation/rule/uuid.rb".freeze, "lib/validation/validator.rb".freeze, "lib/validation/version.rb".freeze] s.homepage = "https://github.com/zombor/Validator".freeze s.licenses = ["ISC".freeze] s.rubygems_version = "2.5.2.1".freeze s.summary = "A standalone, generic object validator for ruby".freeze end valid-1.2.0/lib/0000755000004100000410000000000013314620175013411 5ustar www-datawww-datavalid-1.2.0/lib/validation.rb0000644000004100000410000000027413314620175016073 0ustar www-datawww-datarequire 'validation/validator' module Validation class << self private def included(mod) mod.module_eval do extend Validation::Rules end end end end valid-1.2.0/lib/validation/0000755000004100000410000000000013314620175015543 5ustar www-datawww-datavalid-1.2.0/lib/validation/version.rb0000644000004100000410000000005213314620175017552 0ustar www-datawww-datamodule Validation VERSION = '1.2.0' end valid-1.2.0/lib/validation/validator.rb0000644000004100000410000000746513314620175020071 0ustar www-datawww-datamodule Validation module Rules # A hash of rules for this object def rules @rules ||= {} end # A hash of errors for this object def errors @errors ||= {} end # Define a rule for this object # # The rule parameter can be one of the following: # # * a symbol that matches to a class in the Validation::Rule namespace # * e.g. rule(:field, :not_empty) # * a hash containing the rule as the key and it's parameters as the values # * e.g. rule(:field, :length => { :minimum => 3, :maximum => 5 }) # * an array combining the two previous types def rule(field, definition) field = field.to_sym rules[field] = [] if rules[field].nil? begin if definition.respond_to?(:each_pair) add_parameterized_rules(field, definition) elsif definition.respond_to?(:each) definition.each do |item| if item.respond_to?(:each_pair) add_parameterized_rules(field, item) else add_single_rule(field, item) end end else add_single_rule(field, definition) end rescue NameError => e raise InvalidRule.new(e) end self end # Determines if this object is valid. When a rule fails for a field, # this will stop processing further rules. In this way, you'll only get # one error per field def valid? valid = true rules.each_pair do |field, rules| if ! @obj.respond_to?(field) raise InvalidKey, "cannot validate non-existent field '#{field}'" end rules.each do |r| if ! r.valid_value?(@obj.send(field)) valid = false errors[field] = {:rule => r.error_key, :params => r.params} break end end end @valid = valid end protected # Adds a single rule to this object def add_single_rule(field, key_or_klass, params = nil) klass = if key_or_klass.respond_to?(:new) key_or_klass else get_rule_class_by_name(key_or_klass) end args = [params].compact rule = klass.new(*args) rule.obj = @obj if rule.respond_to?(:obj=) rules[field] << rule end # Adds a set of parameterized rules to this object def add_parameterized_rules(field, rules) rules.each_pair do |key, params| add_single_rule(field, key, params) end end # Resolves the specified rule name to a rule class def get_rule_class_by_name(klass) klass = camelize(klass) Validation::Rule.const_get(klass) rescue NameError => e raise InvalidRule.new(e) end # Converts a symbol to a class name, taken from rails def camelize(term) string = term.to_s string = string.sub(/^[a-z\d]*/) { $&.capitalize } string.gsub(/(?:_|(\/))([a-z\d]*)/i) { $2.capitalize }.gsub('/', '::') end end # Validator is a simple ruby validation class. You don't use it directly # inside your classes like just about every other ruby validation class out # there. I chose to implement it in this way so I didn't automatically # pollute the namespace of the objects I wanted to validate. # # This also solves the problem of validating forms very nicely. Frequently # you will have a form that represents many different data objects in your # system, and you can pre-validate everything before doing any saving. class Validator include Validation::Rules def initialize(obj) @rules = self.class.rules if self.class.is_a?(Validation::Rules) @obj = obj end end # InvalidKey is raised if a rule is added to a field that doesn't exist class InvalidKey < RuntimeError end # InvalidRule is raised if a rule is added that doesn't exist class InvalidRule < RuntimeError end end valid-1.2.0/lib/validation/rule/0000755000004100000410000000000013314620175016512 5ustar www-datawww-datavalid-1.2.0/lib/validation/rule/phone.rb0000644000004100000410000000141413314620175020150 0ustar www-datawww-datamodule Validation module Rule # Phone rule class Phone # params can be any of the following: # # - :format - the phone number format # # Example: # # {:format => :america} def initialize(params = {:format => :america}) @params = params end # returns the params given in the constructor def params @params end # determines if value is valid according to the constructor params def valid_value?(value) send(@params[:format], value) end def error_key :phone end protected def america(value) digits = value.gsub(/\D/, '').split(//) digits.length == 10 || digits.length == 11 end end end end valid-1.2.0/lib/validation/rule/uri.rb0000644000004100000410000000112413314620175017634 0ustar www-datawww-datamodule Validation module Rule class URI def initialize(parts=[:host]) @required_parts = parts end def error_key :uri end def params {:required_elements => @required_parts} end def valid_value?(uri_string) return true if uri_string.nil? uri = URI(uri_string) @required_parts.each do |part| if uri.send(part).nil? || uri.send(part).empty? return false end end true rescue ::URI::InvalidURIError return false end end end end valid-1.2.0/lib/validation/rule/regular_expression.rb0000644000004100000410000000052413314620175022760 0ustar www-datawww-datamodule Validation module Rule class RegularExpression def initialize(params) @params = params end def error_key :regular_expression end def valid_value?(value) value.nil? || !!@params[:regex].match(value) end def params @params end end end end valid-1.2.0/lib/validation/rule/length.rb0000644000004100000410000000175613314620175020331 0ustar www-datawww-datamodule Validation module Rule # Length rule class Length # params can be any of the following: # # - :minimum - at least this many chars # - :maximum - at most this many chars # - :exact - exactly this many chars # # Example: # # {:minimum => 3, :maximum => 10} # {:exact => 10} def initialize(params) @params = params end # returns the params given in the constructor def params @params end # determines if value is valid according to the constructor params def valid_value?(value) @params.each_pair do |key, param| return false if key == :minimum && (value.nil? || value.length < param) return false if key == :maximum && !value.nil? && value.length > param return false if key == :exact && (value.nil? || value.length != param) end true end def error_key :length end end end end valid-1.2.0/lib/validation/rule/uuid.rb0000644000004100000410000000203013314620175020000 0ustar www-datawww-datamodule Validation # UUID rule module Rule class Uuid class UnknownVersion < StandardError; end # params can be any of the folowing: # # - :version - v4 # v5 # uuid (Any valid uuid) # # Example: # # {:version => v4} def initialize(params) @params = params end def params @params end def valid_value?(value) value.nil? || !!uuid_regex.match(value.to_s) rescue UnknownVersion false end def error_key :uuid end private VERSION_REGEX = { 'uuid' => /^[0-9A-F]{8}-[0-9A-F]{4}-[1-5][0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i, 'v4' => /^[0-9A-F]{8}-[0-9A-F]{4}-4[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i, 'v5' => /^[0-9A-F]{8}-[0-9A-F]{4}-5[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i, } def uuid_regex VERSION_REGEX.fetch(params[:version]) { raise UnknownVersion } end end end end valid-1.2.0/lib/validation/rule/numeric.rb0000644000004100000410000000062513314620175020504 0ustar www-datawww-datamodule Validation module Rule # rule for numeric values class Numeric # Determines if value is numeric. It can only contain whole numbers def valid_value?(value) !!/^[0-9]+$/.match(value.to_s) end # The error key for this rule def error_key :numeric end # this rule has no params def params {} end end end end valid-1.2.0/lib/validation/rule/matches.rb0000644000004100000410000000144713314620175020471 0ustar www-datawww-datamodule Validation module Rule # Matches rule class Matches attr_writer :obj # This class should take the field to match with in the constructor: # # rule = Validation::Rule::Matches(:password) # rule.obj = OpenStruct.new(:password => 'foo') # rule.valid_value?('foo') def initialize(matcher_field) @matcher_field = matcher_field end # The error key for this rule def error_key :matches end # Params is the matcher_field given in the constructor def params @matcher_field end # Determines if value matches the field given in the constructor def valid_value?(value) matcher_value = @obj.send(@matcher_field) matcher_value == value end end end end valid-1.2.0/lib/validation/rule/email.rb0000644000004100000410000000332013314620175020124 0ustar www-datawww-datamodule Validation module Rule # Email rule class. This rule was adapted from https://github.com/emmanuel/aequitas/blob/master/lib/aequitas/rule/format/email_address.rb class Email EMAIL_ADDRESS = begin letter = 'a-zA-Z' digit = '0-9' atext = "[#{letter}#{digit}\!\#\$\%\&\'\*+\/\=\?\^\_\`\{\|\}\~\-]" dot_atom_text = "#{atext}+([.]#{atext}*)+" dot_atom = dot_atom_text no_ws_ctl = '\x01-\x08\x11\x12\x14-\x1f\x7f' qtext = "[^#{no_ws_ctl}\\x0d\\x22\\x5c]" # Non-whitespace, non-control character except for \ and " text = '[\x01-\x09\x11\x12\x14-\x7f]' quoted_pair = "(\\x5c#{text})" qcontent = "(?:#{qtext}|#{quoted_pair})" quoted_string = "[\"]#{qcontent}+[\"]" atom = "#{atext}+" word = "(?:#{atom}|#{quoted_string})" obs_local_part = "#{word}([.]#{word})*" local_part = "(?:#{dot_atom}|#{quoted_string}|#{obs_local_part})" dtext = "[#{no_ws_ctl}\\x21-\\x5a\\x5e-\\x7e]" dcontent = "(?:#{dtext}|#{quoted_pair})" domain_literal = "\\[#{dcontent}+\\]" obs_domain = "#{atom}([.]#{atom})+" domain = "(?:#{dot_atom}|#{domain_literal}|#{obs_domain})" addr_spec = "#{local_part}\@#{domain}" pattern = /\A#{addr_spec}\z/u end # Determines if value is a valid email def valid_value?(value) !!EMAIL_ADDRESS.match(value) end # The error key for this rule def error_key :email end # This rule has no params def params {} end end end end valid-1.2.0/lib/validation/rule/not_empty.rb0000644000004100000410000000062313314620175021056 0ustar www-datawww-datamodule Validation module Rule # Rule for not empty class NotEmpty # This rule has no params def params {} end # Determines if value is empty or not. In this rule, nil is empty def valid_value?(value) ! (value.nil? || value.empty?) end # The error key for this field def error_key :not_empty end end end end