├── .gitignore ├── .rspec ├── .travis.yml ├── CHANGELOG.md ├── Gemfile ├── LICENSE.txt ├── README.markdown ├── Rakefile ├── lib ├── validates_formatting_of.rb └── validates_formatting_of │ ├── method.rb │ ├── model_additions.rb │ ├── railtie.rb │ ├── validation.rb │ ├── validation_addition.rb │ ├── validator.rb │ └── version.rb ├── spec ├── spec_helper.rb └── validates_formatting_of │ ├── model_additions_spec.rb │ ├── validation_addition_spec.rb │ ├── validation_spec.rb │ └── validator_spec.rb └── validates_formatting_of.gemspec /.gitignore: -------------------------------------------------------------------------------- 1 | *.gem 2 | *.rbc 3 | .bundle 4 | .config 5 | .yardoc 6 | Gemfile.lock 7 | InstalledFiles 8 | _yardoc 9 | coverage 10 | doc/ 11 | lib/bundler/man 12 | pkg 13 | rdoc 14 | spec/reports 15 | test/tmp 16 | test/version_tmp 17 | tmp 18 | .ruby-version 19 | .overcommit.yml 20 | -------------------------------------------------------------------------------- /.rspec: -------------------------------------------------------------------------------- 1 | --color 2 | --order rand 3 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | script: bundle exec rspec spec 2 | rvm: 3 | - 1.9.3 4 | - 2.0.0 5 | - 2.1.0 6 | - 2.2.2 7 | - jruby-19mode 8 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## v0.8.1 2 | 3 | * Support Rails 4 4 | 5 | ## v0.8.0 6 | 7 | * Added Rails 'sexy' validation. *hbakhiyor* 8 | 9 | ```ruby 10 | class User < ActiveRecord::Base 11 | validates :email, :email => true 12 | end 13 | ``` 14 | 15 | ## v0.7.2 16 | 17 | * Bugfix: Changed \Z to \z anchor and added some test assertions. Not valid with newline in some formats *hbakhiyor* 18 | 19 | ## v0.7.1 20 | 21 | * Removed :ip_address ArgumentError. Already fails since it is missing 22 | 23 | ## v0.7.0 24 | 25 | * Removed :ip_address validation method 26 | * Bug fix for :simple_email validation. Identical to :email validation. 27 | 28 | There were a few changes between v0.5.0 and v0.7.0, however I neglected to updated them here. They are as follows: 29 | 30 | * Refactored entire gem for better testing 31 | * Deprecating and then removing :ip_address validation in favor of :ip_address_v4 validation. 32 | 33 | ## v0.5.0 34 | * Dropped support for Ruby 1.8.7 35 | * Dropped support for REE 36 | * Updated email regex so that hosts/domains cannot start or end with hyphens. 37 | 38 | ## v0.4.1 39 | * __Removed Ruby-specific Regex flags in email.__ This was breaking an implementation in another project which used the `client_side_validations` gem which pulled in the Regex directly from the model. As the `u` and `x` flags are not supported by javascript, this made `client_side_validations` entirely useless. 40 | 41 | ## v0.4.0 42 | 43 | * Email and phone validations more flexible. 44 | * Can now pass options such as `:if`, `:unless`, and `:on` to `validates_formatting_of` 45 | 46 | ## v0.3.7 47 | 48 | * Bugfix in `:allow_nil` and `:allow_blank` 49 | 50 | ## v0.3.6 51 | 52 | * Added a small mention of how to suggest validation patterns 53 | * Added validation method for dollar amounts 54 | 55 | ## v0.3.5 56 | 57 | * Quick release to fix Ruby environment bugs introduced in v0.3.4. 58 | 59 | ## v0.3.4 60 | 61 | * Introduced default error messages. 62 | * *Notice* This release did not work in all Ruby environments. 63 | 64 | ## v0.3.0 -- v0.3.1 65 | 66 | * `:allow_nil` and `:allow_blank` validation options added 67 | * gemspec modifications for better gem management 68 | * More testing for custom messages and validations 69 | 70 | ## v0.2.1 -- v0.2.3 71 | 72 | * Added several new methods and tests for validations. 73 | * Fixed several spelling and English issues in the README. 74 | 75 | ## v0.2.0 76 | 77 | * initial release 78 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | # Specify your gem's dependencies in validates_format_of.gemspec 4 | gemspec 5 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012 Matt Bridges 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | -------------------------------------------------------------------------------- /README.markdown: -------------------------------------------------------------------------------- 1 | [![Build Status](https://secure.travis-ci.org/mattdbridges/validates_formatting_of.png)](http://travis-ci.org/mattdbridges/validates_formatting_of) 2 | [![Dependency Status](https://gemnasium.com/mattdbridges/validates_formatting_of.png?travis)](https://gemnasium.com/mattdbridges/validates_formatting_of) 3 | [![Code Climate](https://codeclimate.com/github/mattdbridges/validates_formatting_of.png)](https://codeclimate.com/github/mattdbridges/validates_formatting_of) 4 | 5 | # Validates Formatting Of 6 | 7 | The `validates_formatting_of` gem adds several convenient methods to validate things such as emails, urls, and phone numbers in a Rails application. 8 | 9 | # Supported Ruby Versions 10 | 11 | * 1.9.3 12 | * 2.0.0 13 | * 2.1.0 14 | * 2.2.0 15 | 16 | # Installation 17 | 18 | To install `validates_formatting_of`, add the following to your `Gemfile`: 19 | 20 | gem 'validates_formatting_of' 21 | 22 | Then bundle install: 23 | 24 | bundle install 25 | 26 | # Usage 27 | 28 | Using `validates_formatting_of` is as simple as using Rails' built-in validation methods in models. 29 | 30 | ```ruby 31 | class User < ActiveRecord::Base 32 | validates_formatting_of :email 33 | end 34 | ``` 35 | 36 | If the name of the column is identical to the validation method you would use, it auto-selects that validation method. Thus, this is a shortcut for the following: 37 | 38 | ```ruby 39 | class User < ActiveRecord::Base 40 | validates_formatting_of :email, :using => :email 41 | end 42 | ``` 43 | 44 | This call will ensure that the user-provided email is a valid email. This way, you will not need to find or write your own regex to validate. All of that logic is contained within `validates_formatting_of`. 45 | 46 | # Rails validation options still available 47 | 48 | You can still add the following options when using `validates_formatting_of`: 49 | 50 | * `:allow_nil` 51 | * `:allow_blank` 52 | * `:on` 53 | * `:if` 54 | * `:unless` 55 | * You can also specify the `:message` option to use a custom validation message. 56 | 57 | # Share your Validations 58 | 59 | Say, for example, you have identical plain-old regex validations for different columns or even on different models entirely. You can easily alleviate this problem by simply adding the validation(s) in an initializer file. 60 | 61 | While very unrealistic, these examples should serve their purpose in demonstrating this ability. 62 | 63 | ```ruby 64 | # config/initializers/validates_formatting_of.rb 65 | ValidatesFormattingOf::Method.add :loweralpha, /[a-z]/, "must be lowercase and no spaces" 66 | ValidatesFormattingOf::Method.add :upperalpha, /[A-Z]/, "must be uppercase and no spaces" 67 | ValidatesFormattingOf::Method.add :weak_password, /[a-zA-Z0-9]{8,}/, "must contain only letters and numbers and be at least 8 characters long". 68 | ``` 69 | 70 | Keep in mind, since this gem is only ActiveModel-dependent, you should be able to do this in whatever non-Rails application classes you have that include `ActiveModel::Validations` in some way (and that extend the `ValidatesFormattingOf::ModelAdditons` module). 71 | 72 | # Built-in Validations 73 | 74 | `validates_formatting_of` has the following built-in validations: 75 | 76 | ```ruby 77 | class ExampleModel < ActiveRecord::Base 78 | validates_formatting_of :email, :using => :email # Email 79 | validates_formatting_of :first_name, :using => :alpha # Letters 80 | validates_formatting_of :website, :using => :url # URLs 81 | validates_formatting_of :text, :using => :alphanum # Alpha-numeric 82 | validates_formatting_of :zipcode, :using => :us_zip # US Zip Code 83 | validates_formatting_of :phone, :using => :us_phone # US Phone Numbers 84 | validates_formatting_of :ip, :using => :ip_address_v4 # IPv4 85 | validates_formatting_of :ssn, :using => :ssn # Social Security Numbers 86 | validates_formatting_of :color, :using => :hex_color # Hexadecimal Colors 87 | validates_formatting_of :amount, :using => :dollars # Dollars 88 | 89 | # Credit Card (Visa, Mastercard, Discover, and American Express) 90 | validates_formatting_of :cc, :using => :credit_card 91 | end 92 | ``` 93 | 94 | **Note**: If you use `client_side_validations` then you need to use the following validation method: 95 | 96 | ```ruby 97 | class User < ActiveRecord::Base 98 | validates_formatting_of :email, :using => :simple_email 99 | end 100 | ``` 101 | 102 | ### Plain Old Ruby Objects 103 | 104 | If you are not using ActiveRecord or want to use it on some other type of object, this is the least you need to get validations running. 105 | 106 | ```ruby 107 | class User 108 | include ActiveModel::Validations 109 | extend ValidatesFormattingOf::ModelAdditions 110 | 111 | attr_accessor :email 112 | 113 | validates_formatting_of :email, :using => :email 114 | end 115 | ``` 116 | 117 | # Over-writable 118 | 119 | If, for any reason, you want to overwrite the regex specified in the gem, you can using the `:with` option just like in ActiveModel's built-in `validates_format_of`. 120 | 121 | ```ruby 122 | class Person < ActiveRecord::Base 123 | validates_formatting_of :first_name, :with => /[A-Z]/i 124 | end 125 | ``` 126 | 127 | # Development and Contribution 128 | 129 | To add a simple regex validation, all that is necessary is to add a single line to the `ValidatesFormattingOf::Method` module in the `lib/method.rb` file (with a line or two of documentation explaining it's use). 130 | 131 | For example: 132 | 133 | ```ruby 134 | module ValidatesFormattingOf::Method 135 | # This :validation_name method is for example purposes only. 136 | # You can use this in production, but it would require a value of 'example regex' to pass. 137 | add :validation_name, %r{example regex}iux, "is a message for validation method :validation_name" 138 | end 139 | ``` 140 | 141 | 1. Fork it 142 | 2. Make it awesome (with passing tests) 143 | 3. Create a new Pull Request. 144 | 145 | # Have Ideas? 146 | 147 | Do you use a particular pattern on a regular basis that isn't here or you would like to contribute? For now, [create a new issue](https://github.com/mattdbridges/validates_formatting_of/issues/new) in the issue tracker. I would be more than happy to consider adding it to the project. 148 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require 'bundler/gem_tasks' 2 | require 'rspec/core/rake_task' 3 | 4 | RSpec::Core::RakeTask.new(:spec) 5 | 6 | task :default => :spec 7 | -------------------------------------------------------------------------------- /lib/validates_formatting_of.rb: -------------------------------------------------------------------------------- 1 | require "validates_formatting_of/version" 2 | require "validates_formatting_of/method" 3 | require "validates_formatting_of/validator" 4 | require "validates_formatting_of/model_additions" 5 | require "validates_formatting_of/railtie" if defined? Rails -------------------------------------------------------------------------------- /lib/validates_formatting_of/method.rb: -------------------------------------------------------------------------------- 1 | require 'validates_formatting_of/validation' 2 | require 'validates_formatting_of/validation_addition' 3 | 4 | module ValidatesFormattingOf 5 | module Method 6 | 7 | extend ValidationAddition 8 | 9 | # This method is very close to allowing what is specified in RFC 5322 and RFC 5321 10 | add :email, %r{\A([^@\s]+)@((?:(?!-)[-a-z0-9]+(? :email 11 | # end 12 | # 13 | # If your column name is idencital to any of the built-in methods, you 14 | # may leave off the `:using` option and validates_formatting_of will 15 | # automatically use the validation with the matching name. 16 | # 17 | # class User < ActiveRecord::Base 18 | # validates_formatting_of :email 19 | # end 20 | # 21 | # You can also pass conditions and options for Rails to use 22 | # * :if 23 | # * :unless 24 | # * :allow_nil 25 | # * :allow_blank 26 | # * :on 27 | def validates_formatting_of(attribute, options = {}) 28 | validation = Method.find(attribute, options) 29 | options.reverse_merge!(:with => validation.regex, :message => validation.message) 30 | self.validates_format_of(attribute, options) 31 | end 32 | 33 | end 34 | end 35 | -------------------------------------------------------------------------------- /lib/validates_formatting_of/railtie.rb: -------------------------------------------------------------------------------- 1 | # Extend ActiveRecord's methods 2 | module ValidatesFormattingOf 3 | class Railtie < Rails::Railtie 4 | initializer 'validates_formatting_of.model_additions' do 5 | ActiveSupport.on_load :active_record do 6 | extend ModelAdditions 7 | end 8 | end 9 | 10 | initializer 'validates_formatting_of.validations' do 11 | ActiveSupport.on_load :active_record do 12 | include Validations 13 | end 14 | end 15 | end 16 | end -------------------------------------------------------------------------------- /lib/validates_formatting_of/validation.rb: -------------------------------------------------------------------------------- 1 | module ValidatesFormattingOf 2 | 3 | class InvalidRegularExpression < StandardError 4 | def initialize(name) 5 | super("You must specify a Regexp, a proc, or a lambda for the #{name.inspect} validation.") 6 | end 7 | end 8 | 9 | class Validation 10 | attr_reader :name, :regex, :message 11 | 12 | def initialize(name, regexp, message = "is not correctly formatted") 13 | callable = regexp.respond_to? :call 14 | if !callable && regexp.class.to_s != "Regexp" 15 | raise InvalidRegularExpression.new(name) 16 | end 17 | @name, @regex, @message = name, regexp, message 18 | end 19 | 20 | def inspect 21 | "#" 22 | end 23 | 24 | def to_s 25 | "" 26 | end 27 | end 28 | end 29 | -------------------------------------------------------------------------------- /lib/validates_formatting_of/validation_addition.rb: -------------------------------------------------------------------------------- 1 | require 'active_support/core_ext/object/blank' 2 | 3 | module ValidatesFormattingOf 4 | 5 | class MissingValidation < StandardError 6 | def initialize(method) 7 | super("The validation method #{method.to_sym.inspect} has not been defined.") 8 | end 9 | end 10 | 11 | module ValidationAddition 12 | attr_reader :validations 13 | 14 | def add(name, regex, message = nil) 15 | @validations ||= {} 16 | @validations[name.to_s] = Validation.new(name.to_sym, regex, message) 17 | end 18 | 19 | def find(attribute, opts = {}) 20 | method = opts.fetch(:using, attribute) 21 | raise MissingValidation.new(method) if missing? method 22 | @validations[method.to_s] 23 | end 24 | 25 | def missing?(name) 26 | !exists?(name) 27 | end 28 | 29 | def exists?(name) 30 | @validations[name.to_s].present? 31 | end 32 | end 33 | end 34 | -------------------------------------------------------------------------------- /lib/validates_formatting_of/validator.rb: -------------------------------------------------------------------------------- 1 | require 'active_support/core_ext/hash/reverse_merge' 2 | require 'active_support/core_ext/string' 3 | require 'active_support/concern' 4 | require 'active_model/validator' 5 | require 'active_model/validations' 6 | 7 | 8 | module ValidatesFormattingOf 9 | module Validations 10 | class Validator < ActiveModel::Validations::FormatValidator 11 | def initialize(options = {}, format = nil) 12 | return if format.blank? 13 | 14 | validation = Method.find(nil, :using => format) 15 | options.reverse_merge!(:with => validation.regex, :message => validation.message) 16 | super options 17 | end 18 | end 19 | 20 | Method.validations.each do |key, value| 21 | class_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1 22 | class #{key.to_s.camelize}Validator < Validator 23 | def initialize(options = {}) 24 | super options, #{key.to_sym.inspect} 25 | end 26 | end 27 | RUBY_EVAL 28 | end 29 | end 30 | end 31 | -------------------------------------------------------------------------------- /lib/validates_formatting_of/version.rb: -------------------------------------------------------------------------------- 1 | module ValidatesFormattingOf 2 | VERSION = "0.9.0" 3 | end 4 | -------------------------------------------------------------------------------- /spec/spec_helper.rb: -------------------------------------------------------------------------------- 1 | require 'simplecov' 2 | 3 | if ENV["RUN_SIMPLECOV"] == 'true' 4 | SimpleCov.start do 5 | load_adapter 'test_frameworks' 6 | end 7 | end 8 | 9 | RSpec.configure do |config| 10 | config.disable_monkey_patching! 11 | end 12 | 13 | require 'validates_formatting_of' 14 | require 'active_model' 15 | 16 | class TestActiveRecord 17 | 18 | include ActiveModel::Validations 19 | include ValidatesFormattingOf::Validations 20 | extend ValidatesFormattingOf::ModelAdditions 21 | 22 | def initialize(attributes = {}) 23 | attributes.each do |name, value| 24 | send("#{name}=", value) 25 | end 26 | @persisted = false 27 | end 28 | 29 | def save 30 | @persisted = true 31 | end 32 | 33 | def persisted? 34 | @persisted ||= false 35 | end 36 | 37 | end 38 | -------------------------------------------------------------------------------- /spec/validates_formatting_of/model_additions_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | RSpec.describe ValidatesFormattingOf::ModelAdditions do 4 | 5 | describe "email" do 6 | class Email < TestActiveRecord 7 | attr_accessor :email 8 | validates_formatting_of :email 9 | end 10 | it "validates that the email provided is valid" do 11 | expect(Email.new(:email => "example@example.com")).to be_valid 12 | expect(Email.new(:email => "badexample.com")).not_to be_valid 13 | expect(Email.new(:email => "mbridges.91@gmail.com")).to be_valid 14 | expect(Email.new(:email => "some-random%%%strangely-formatted-email@lots.of.subdomains.com")).to be_valid 15 | expect(Email.new(:email => "this__???{}|__should@be-valid.com")).to be_valid 16 | expect(Email.new(:email => "visitorservices@vmfa.museum")).to be_valid 17 | expect(Email.new(:email => "info@samoa.travel")).to be_valid 18 | expect(Email.new(:email => "info@-samoa.travel")).not_to be_valid 19 | expect(Email.new(:email => "info@samoa-.travel")).not_to be_valid 20 | expect(Email.new(:email => "info@123-samoa.travel")).to be_valid 21 | expect(Email.new(:email => "info@123-samoa.travel\n")).not_to be_valid 22 | end 23 | end 24 | 25 | describe "simple email for 1.8.7 and javascript validations (such as with client_side_validations)" do 26 | class SimpleEmail < TestActiveRecord 27 | attr_accessor :email 28 | validates_formatting_of :email, :using => :simple_email 29 | end 30 | it "validates that the email provided is valid" do 31 | expect(SimpleEmail.new(:email => "example@example.com")).to be_valid 32 | expect(SimpleEmail.new(:email => "badexample.com")).not_to be_valid 33 | expect(SimpleEmail.new(:email => "mbridges.91@gmail.com")).to be_valid 34 | expect(SimpleEmail.new(:email => "some-random%%%strangely-formatted-email@lots.of.subdomains.com")).to be_valid 35 | expect(SimpleEmail.new(:email => "this__???{}|__should@be-valid.com")).to be_valid 36 | expect(SimpleEmail.new(:email => "visitorservices@vmfa.museum")).to be_valid 37 | expect(SimpleEmail.new(:email => "info@samoa.travel")).to be_valid 38 | expect(SimpleEmail.new(:email => "info@-samoa.travel")).to be_valid 39 | expect(SimpleEmail.new(:email => "info@samoa-.travel")).to be_valid 40 | expect(SimpleEmail.new(:email => "info@123-samoa.travel")).to be_valid 41 | expect(SimpleEmail.new(:email => "info@123-samoa.travel\n")).not_to be_valid 42 | end 43 | end 44 | describe "url" do 45 | class Webpage < TestActiveRecord 46 | attr_accessor :url 47 | validates_formatting_of :url 48 | end 49 | it "validates that the url provided is valid" do 50 | expect(Webpage.new(:url => 'http://something.com')).to be_valid 51 | expect(Webpage.new(:url => 'http://something-else.com')).to be_valid 52 | expect(Webpage.new(:url => 'http://sub.domains.something-else.com')).to be_valid 53 | expect(Webpage.new(:url => 'http://username:password@something-else.com')).to be_valid 54 | expect(Webpage.new(:url => "http://username:password@something-else.com\n")).not_to be_valid 55 | expect(Webpage.new(:url => "something else")).not_to be_valid 56 | end 57 | end 58 | 59 | describe "us_zip" do 60 | class USZip < TestActiveRecord 61 | attr_accessor :zipcode 62 | validates_formatting_of :zipcode, :using => :us_zip 63 | end 64 | it "validates that the zipcode provided is valid" do 65 | expect(USZip.new(:zipcode => '92348')).to be_valid 66 | expect(USZip.new(:zipcode => '23434-2348')).to be_valid 67 | expect(USZip.new(:zipcode => "23434-2348\n")).not_to be_valid 68 | expect(USZip.new(:zipcode => '234')).not_to be_valid 69 | expect(USZip.new(:zipcode => '23408234')).not_to be_valid 70 | expect(USZip.new(:zipcode => 'invalid')).not_to be_valid 71 | end 72 | end 73 | 74 | describe "alpha" do 75 | class Alpha < TestActiveRecord 76 | attr_accessor :alpha 77 | validates_formatting_of :alpha 78 | end 79 | it "validates that the letters provided is valid" do 80 | expect(Alpha.new(:alpha => 'abscdsofjsdpfahdsofkajlsdfaspdhjfads')).to be_valid 81 | expect(Alpha.new(:alpha => 'asdfalskdfjhas-dlfhasdksdfaldhfadsfasdfa')).to be_valid 82 | expect(Alpha.new(:alpha => 'adsufasodfksadjfskjdfha98')).not_to be_valid 83 | expect(Alpha.new(:alpha => 'asdf ausdpf98hasdfo alsdf ja8 sd')).not_to be_valid 84 | end 85 | end 86 | 87 | describe "alphanum" do 88 | class Alphanum < TestActiveRecord 89 | attr_accessor :letters_and_numbers 90 | validates_formatting_of :letters_and_numbers, :using => :alphanum 91 | end 92 | it "validates that the letters provided is valid" do 93 | expect(Alphanum.new(:letters_and_numbers => 'numbersandlettersarevalid1234567890')).to be_valid 94 | expect(Alphanum.new(:letters_and_numbers => 'justletters')).to be_valid 95 | expect(Alphanum.new(:letters_and_numbers => 'letters and numbers 123 with spaces')).to be_valid 96 | expect(Alphanum.new(:letters_and_numbers => 'adding ; some special ** chars')).not_to be_valid 97 | end 98 | end 99 | 100 | describe "us_phone" do 101 | class USPhone < TestActiveRecord 102 | attr_accessor :phone_number 103 | validates_formatting_of :phone_number, :using => :us_phone 104 | end 105 | it "validates that the phone number provided is valid" do 106 | expect(USPhone.new(:phone_number => '(234) 234-3456')).to be_valid 107 | expect(USPhone.new(:phone_number => '123 123 3456')).to be_valid 108 | expect(USPhone.new(:phone_number => '1231233456')).to be_valid 109 | expect(USPhone.new(:phone_number => '123.123.3456')).to be_valid 110 | expect(USPhone.new(:phone_number => '(223)123-2347')).to be_valid 111 | expect(USPhone.new(:phone_number => "(223)123-2347\n")).not_to be_valid 112 | expect(USPhone.new(:phone_number => '(223 123-2347')).not_to be_valid 113 | expect(USPhone.new(:phone_number => '12349870238')).not_to be_valid 114 | end 115 | end 116 | 117 | describe "ip_address_v4" do 118 | class IPAddress < TestActiveRecord 119 | attr_accessor :ipv4 120 | validates_formatting_of :ipv4, :using => :ip_address_v4 121 | end 122 | it "validates that the IP address provided is valid" do 123 | expect(IPAddress.new(:ipv4 => '10.10.10')).not_to be_valid 124 | expect(IPAddress.new(:ipv4 => '999.10.10.20')).not_to be_valid 125 | expect(IPAddress.new(:ipv4 => '2222.22.22.22')).not_to be_valid 126 | expect(IPAddress.new(:ipv4 => '22.2222.22.2')).not_to be_valid 127 | expect(IPAddress.new(:ipv4 => '127.0.0.1')).to be_valid 128 | expect(IPAddress.new(:ipv4 => '132.254.111.10')).to be_valid 129 | expect(IPAddress.new(:ipv4 => "132.254.111.10\n")).not_to be_valid 130 | end 131 | end 132 | 133 | # For clarification, NONE of the following numbers are real credit card numbers. 134 | # They only match the pattern. These were randomly made for testing. 135 | describe "credit_card" do 136 | class Client < TestActiveRecord 137 | attr_accessor :cc 138 | validates_formatting_of :cc, :using => :credit_card 139 | end 140 | it "validates that the credit card number provided is valid" do 141 | expect(Client.new(:cc => '4264-2879-1230-0000')).to be_valid # Visa style 142 | expect(Client.new(:cc => '6011-1111-0000-2391')).to be_valid # Discover style 143 | expect(Client.new(:cc => '5422434400828888')).to be_valid # Mastercard style 144 | expect(Client.new(:cc => "5422434400828889\n")).not_to be_valid # Mastercard style 145 | expect(Client.new(:cc => '1233444444444444')).not_to be_valid # fake 146 | end 147 | end 148 | 149 | describe "ssn" do 150 | class AnotherPerson < TestActiveRecord 151 | attr_accessor :ssn 152 | validates_formatting_of :ssn 153 | end 154 | it "validates that the social security number provided is valid" do 155 | expect(AnotherPerson.new(:ssn => "145.47.0191")).to be_valid 156 | expect(AnotherPerson.new(:ssn => "223-43-2343")).to be_valid 157 | expect(AnotherPerson.new(:ssn => "999.55.8888")).to be_valid 158 | expect(AnotherPerson.new(:ssn => "999.55.8888\n")).not_to be_valid 159 | expect(AnotherPerson.new(:ssn => "28934")).not_to be_valid 160 | expect(AnotherPerson.new(:ssn => "228934828934934")).not_to be_valid 161 | expect(AnotherPerson.new(:ssn => "23498.7234")).not_to be_valid 162 | end 163 | end 164 | 165 | describe "hex_color" do 166 | class Color < TestActiveRecord 167 | attr_accessor :color 168 | validates_formatting_of :color, :using => :hex_color 169 | end 170 | it "validates that the hex color value provided is valid" do 171 | expect(Color.new(:color => "efefef")).to be_valid 172 | expect(Color.new(:color => "98de89")).to be_valid 173 | expect(Color.new(:color => "000011")).to be_valid 174 | expect(Color.new(:color => "132")).to be_valid 175 | expect(Color.new(:color => "eef")).to be_valid 176 | expect(Color.new(:color => "eef\n")).not_to be_valid 177 | expect(Color.new(:color => "efefe")).not_to be_valid 178 | expect(Color.new(:color => "zsdfsd")).not_to be_valid 179 | expect(Color.new(:color => "p98hul;")).not_to be_valid 180 | expect(Color.new(:color => "sdfsdfsf")).not_to be_valid 181 | end 182 | end 183 | 184 | describe "validation options" do 185 | class Phony < TestActiveRecord 186 | attr_accessor :phone, :phone2 187 | validates_formatting_of :phone, :using => :us_phone, :on => :create 188 | validates_formatting_of :phone2, :using => :us_phone, :on => :update 189 | end 190 | it "validates the phone formatting only on creation" do 191 | option = Phony.new(:phone => "(123) 234-4567") 192 | expect(option).to be_valid 193 | option.phone = "123123123" 194 | expect(option).to be_valid 195 | end 196 | 197 | class Iffy < TestActiveRecord 198 | attr_accessor :name, :phone 199 | validates_presence_of :name 200 | validates_formatting_of :phone, :using => :us_phone, :if => lambda { |iffy| iffy.name == "Matthew" } 201 | end 202 | it "validates the phone formatting only if a name is specified" do 203 | expect(Iffy.new(:phone => "(123 345-4567", :name => "Bill")).to be_valid 204 | expect(Iffy.new(:phone => "(123 345-4567", :name => "Matthew")).not_to be_valid 205 | end 206 | 207 | class Unlessy < TestActiveRecord 208 | attr_accessor :name, :phone 209 | validates_presence_of :name 210 | validates_formatting_of :phone, :using => :us_phone, :unless => lambda { |unlessy| unlessy.name == "Matthew" } 211 | end 212 | it "validates the phone formatting only if a name is specified" do 213 | expect(Unlessy.new(:phone => "(123 345-4567", :name => "Bill")).not_to be_valid 214 | expect(Unlessy.new(:phone => "(123 345-4567", :name => "Matthew")).to be_valid 215 | end 216 | end 217 | describe "dollars" do 218 | class Money < TestActiveRecord 219 | attr_accessor :amount 220 | validates_formatting_of :amount, :using => :dollars 221 | end 222 | it "validates that the dollars amount provided is valid" do 223 | expect(Money.new(:amount => "$100.00")).to be_valid 224 | expect(Money.new(:amount => "100.00")).to be_valid 225 | expect(Money.new(:amount => "12,234,343")).to be_valid 226 | expect(Money.new(:amount => "$12.34")).to be_valid 227 | expect(Money.new(:amount => "120,123,232.32")).to be_valid 228 | expect(Money.new(:amount => "$$1111111100")).not_to be_valid 229 | expect(Money.new(:amount => "100;00")).not_to be_valid 230 | expect(Money.new(:amount => "238,3423,42..99")).not_to be_valid 231 | expect(Money.new(:amount => "$-233")).not_to be_valid 232 | end 233 | end 234 | describe "custom messages" do 235 | class Message < TestActiveRecord 236 | attr_accessor :first_name 237 | validates_formatting_of :first_name, :using => :alpha, :message => "is not a valid first name" 238 | end 239 | it "are allowed and can be used in displaying error messages" do 240 | message = Message.new(:first_name => "invalid-first-name-123") 241 | expect(message).not_to be_valid 242 | expect(message.errors.keys.class).to eq Array 243 | expect(message.errors.full_messages.first).to match(/is not a valid first name/) 244 | end 245 | end 246 | 247 | describe "default error messages" do 248 | class Problems < TestActiveRecord 249 | attr_accessor :name 250 | validates_formatting_of :name, :using => :alpha 251 | end 252 | it "set a default error" do 253 | problems = Problems.new(:name => "sdfs12312dfsd") 254 | expect(problems).not_to be_valid 255 | expect(problems.errors.full_messages.first).to match(/letters/i) 256 | email = Email.new(:email => "not.an.email.address") 257 | expect(email).not_to be_valid 258 | expect(email.errors.full_messages.first).to match(/email/i) 259 | end 260 | end 261 | 262 | describe "nil and blank values" do 263 | class PeopleTest < TestActiveRecord 264 | attr_accessor :email, :email2, :email3 265 | validates_formatting_of :email, :allow_nil => true 266 | validates_formatting_of :email2, :using => :email, :allow_blank => true 267 | validates_formatting_of :email3, :using => :email 268 | end 269 | let(:people) { PeopleTest.new(:email => "mbridges.91@gmail.com", :email2 => "mbridges.91@gmail.com", :email3 => "mbridges.91@gmail.com") } 270 | it "should test nil and blank values correctly" do 271 | people.email = nil 272 | expect(people).to be_valid 273 | people.email = "mbridges.91@gmail.com" 274 | people.email2 = "" 275 | expect(people).to be_valid 276 | people.email2 = "mbridges.91@gmail.com" 277 | people.email3 = nil 278 | expect(people).not_to be_valid 279 | end 280 | end 281 | 282 | end 283 | -------------------------------------------------------------------------------- /spec/validates_formatting_of/validation_addition_spec.rb: -------------------------------------------------------------------------------- 1 | require 'validates_formatting_of/validation_addition' 2 | require 'its' 3 | 4 | module ValidatesFormattingOf 5 | 6 | class TestAdding 7 | extend ValidationAddition 8 | def self.clear! 9 | @validations = nil 10 | end 11 | end 12 | 13 | RSpec.describe ValidationAddition do 14 | before do 15 | TestAdding.clear! 16 | TestAdding.add :email, /email/i 17 | end 18 | it "should be able to add new validations" do 19 | TestAdding.add :another, /another/i 20 | expect(TestAdding.validations.count).to eq(2) 21 | expect(TestAdding.validations['email']).to be_instance_of Validation 22 | expect(TestAdding.validations['another']).to be_instance_of Validation 23 | end 24 | describe "find" do 25 | context "implicit validation method" do 26 | subject { TestAdding.find(:email) } 27 | its(:name) { is_expected.to eq(:email) } 28 | its(:regex) { is_expected.to eq(/email/i) } 29 | end 30 | context "explicit validation method" do 31 | subject { TestAdding.find(:non_existent_validation, :using => :email) } 32 | its(:name) { is_expected.to eq(:email) } 33 | its(:regex) { is_expected.to eq(/email/i) } 34 | end 35 | end 36 | it "should raise an error if the method does not exist" do 37 | expect { TestAdding.find(:fake) }.to raise_error MissingValidation 38 | end 39 | it "should be able to determine if the method does not exist" do 40 | expect(TestAdding.exists?(:email)).to be_truthy 41 | expect(TestAdding.exists?(:non_existent)).to be_falsey 42 | end 43 | it "should be able to accept strings for validation names (for namespacing)" do 44 | TestAdding.add "namespace:phone", /namespace/i 45 | expect(TestAdding.exists?("namespace:phone")).to be_truthy 46 | end 47 | it "should be able to determine if the method is missing" do 48 | expect(TestAdding.missing?(:non_existent)).to be_truthy 49 | expect(TestAdding.missing?(:email)).to be_falsey 50 | end 51 | end 52 | end 53 | -------------------------------------------------------------------------------- /spec/validates_formatting_of/validation_spec.rb: -------------------------------------------------------------------------------- 1 | require 'validates_formatting_of/validation' 2 | require 'its' 3 | 4 | module ValidatesFormattingOf 5 | 6 | RSpec.describe Validation do 7 | context "valid validation creation" do 8 | let(:validation) { Validation.new(:name, /something/i, "is an invalid value") } 9 | subject { validation } 10 | its(:name) { is_expected.to eq(:name) } 11 | its(:regex) { is_expected.to eq(%r{something}i) } 12 | its(:message) { is_expected.to eq('is an invalid value') } 13 | its(:to_s) { is_expected.to eq("") } 14 | its(:inspect) { is_expected.to match(/Validation/) } 15 | its(:inspect) { is_expected.to match(/\/something\/i/) } 16 | its(:inspect) { is_expected.to match(/\:name/) } 17 | end 18 | context "invalid validation creation" do 19 | it "should raise an error if the specified regex is not a Regexp objct" do 20 | expect { Validation.new(:name, 123, "is an invalid value") }.to raise_error 21 | end 22 | it "should not raise an error if the specified regex is a proc or a lambda" do 23 | expect { Validation.new(:name, lambda { "my record" }, "is an invalid value") }.not_to raise_error 24 | expect { Validation.new(:name, proc { "my record" }, "is an invalid value") }.not_to raise_error 25 | end 26 | it "should not raise an error if the regex if valid" do 27 | expect { Validation.new(:name, /something/i, "is an invalid value") }.not_to raise_error 28 | end 29 | end 30 | end 31 | 32 | end 33 | -------------------------------------------------------------------------------- /spec/validates_formatting_of/validator_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | RSpec.describe ValidatesFormattingOf::Validations do 4 | 5 | describe "with 'sexy' validation style" do 6 | describe "email" do 7 | class Email < TestActiveRecord 8 | attr_accessor :email 9 | validates :email, :email => true 10 | end 11 | 12 | it "validates that the email provided is valid" do 13 | expect(Email.new(:email => "example@example.com")).to be_valid 14 | expect(Email.new(:email => "badexample.com")).not_to be_valid 15 | expect(Email.new(:email => "mbridges.91@gmail.com")).to be_valid 16 | expect(Email.new(:email => "some-random%%%strangely-formatted-email@lots.of.subdomains.com")).to be_valid 17 | expect(Email.new(:email => "this__???{}|__should@be-valid.com")).to be_valid 18 | expect(Email.new(:email => "visitorservices@vmfa.museum")).to be_valid 19 | expect(Email.new(:email => "info@samoa.travel")).to be_valid 20 | expect(Email.new(:email => "info@-samoa.travel")).not_to be_valid 21 | expect(Email.new(:email => "info@samoa-.travel")).not_to be_valid 22 | expect(Email.new(:email => "info@123-samoa.travel")).to be_valid 23 | expect(Email.new(:email => "info@123-samoa.travel\n")).not_to be_valid 24 | end 25 | end 26 | 27 | describe "simple email for 1.8.7 and javascript validations (such as with client_side_validations)" do 28 | class SimpleEmail < TestActiveRecord 29 | attr_accessor :email 30 | validates :email, :simple_email => true 31 | end 32 | it "validates that the email provided is valid" do 33 | expect(SimpleEmail.new(:email => "example@example.com")).to be_valid 34 | expect(SimpleEmail.new(:email => "badexample.com")).not_to be_valid 35 | expect(SimpleEmail.new(:email => "mbridges.91@gmail.com")).to be_valid 36 | expect(SimpleEmail.new(:email => "some-random%%%strangely-formatted-email@lots.of.subdomains.com")).to be_valid 37 | expect(SimpleEmail.new(:email => "this__???{}|__should@be-valid.com")).to be_valid 38 | expect(SimpleEmail.new(:email => "visitorservices@vmfa.museum")).to be_valid 39 | expect(SimpleEmail.new(:email => "info@samoa.travel")).to be_valid 40 | expect(SimpleEmail.new(:email => "info@-samoa.travel")).to be_valid 41 | expect(SimpleEmail.new(:email => "info@samoa-.travel")).to be_valid 42 | expect(SimpleEmail.new(:email => "info@123-samoa.travel")).to be_valid 43 | expect(SimpleEmail.new(:email => "info@123-samoa.travel\n")).not_to be_valid 44 | end 45 | end 46 | describe "url" do 47 | class Webpage < TestActiveRecord 48 | attr_accessor :url 49 | validates :url, :url => true 50 | end 51 | it "validates that the url provided is valid" do 52 | expect(Webpage.new(:url => 'http://something.com')).to be_valid 53 | expect(Webpage.new(:url => 'http://something-else.com')).to be_valid 54 | expect(Webpage.new(:url => 'http://sub.domains.something-else.com')).to be_valid 55 | expect(Webpage.new(:url => 'http://username:password@something-else.com')).to be_valid 56 | expect(Webpage.new(:url => "http://username:password@something-else.com\n")).not_to be_valid 57 | expect(Webpage.new(:url => "something else")).not_to be_valid 58 | end 59 | end 60 | 61 | describe "us_zip" do 62 | class USZip < TestActiveRecord 63 | attr_accessor :zipcode 64 | validates :zipcode, :us_zip => true 65 | end 66 | it "validates that the zipcode provided is valid" do 67 | expect(USZip.new(:zipcode => '92348')).to be_valid 68 | expect(USZip.new(:zipcode => '23434-2348')).to be_valid 69 | expect(USZip.new(:zipcode => "23434-2348\n")).not_to be_valid 70 | expect(USZip.new(:zipcode => '234')).not_to be_valid 71 | expect(USZip.new(:zipcode => '23408234')).not_to be_valid 72 | expect(USZip.new(:zipcode => 'invalid')).not_to be_valid 73 | end 74 | end 75 | 76 | describe "alpha" do 77 | class Alpha < TestActiveRecord 78 | attr_accessor :alpha 79 | validates :alpha, :alpha => true 80 | end 81 | it "validates that the letters provided is valid" do 82 | expect(Alpha.new(:alpha => 'abscdsofjsdpfahdsofkajlsdfaspdhjfads')).to be_valid 83 | expect(Alpha.new(:alpha => 'asdfalskdfjhas-dlfhasdksdfaldhfadsfasdfa')).to be_valid 84 | expect(Alpha.new(:alpha => 'adsufasodfksadjfskjdfha98')).not_to be_valid 85 | expect(Alpha.new(:alpha => 'asdf ausdpf98hasdfo alsdf ja8 sd')).not_to be_valid 86 | end 87 | end 88 | 89 | describe "alphanum" do 90 | class Alphanum < TestActiveRecord 91 | attr_accessor :letters_and_numbers 92 | validates :letters_and_numbers, :alphanum => true 93 | end 94 | it "validates that the letters provided is valid" do 95 | expect(Alphanum.new(:letters_and_numbers => 'numbersandlettersarevalid1234567890')).to be_valid 96 | expect(Alphanum.new(:letters_and_numbers => 'justletters')).to be_valid 97 | expect(Alphanum.new(:letters_and_numbers => 'letters and numbers 123 with spaces')).to be_valid 98 | expect(Alphanum.new(:letters_and_numbers => 'adding ; some special ** chars')).not_to be_valid 99 | end 100 | end 101 | 102 | describe "us_phone" do 103 | class USPhone < TestActiveRecord 104 | attr_accessor :phone_number 105 | validates :phone_number, :us_phone => true 106 | end 107 | it "validates that the phone number provided is valid" do 108 | expect(USPhone.new(:phone_number => '(234) 234-3456')).to be_valid 109 | expect(USPhone.new(:phone_number => '123 123 3456')).to be_valid 110 | expect(USPhone.new(:phone_number => '1231233456')).to be_valid 111 | expect(USPhone.new(:phone_number => '123.123.3456')).to be_valid 112 | expect(USPhone.new(:phone_number => '(223)123-2347')).to be_valid 113 | expect(USPhone.new(:phone_number => "(223)123-2347\n")).not_to be_valid 114 | expect(USPhone.new(:phone_number => '(223 123-2347')).not_to be_valid 115 | expect(USPhone.new(:phone_number => '12349870238')).not_to be_valid 116 | end 117 | end 118 | 119 | describe "ip_address_v4" do 120 | class IPAddress < TestActiveRecord 121 | attr_accessor :ipv4 122 | validates :ipv4, :ip_address_v4 => true 123 | end 124 | it "validates that the IP address provided is valid" do 125 | expect(IPAddress.new(:ipv4 => '10.10.10')).not_to be_valid 126 | expect(IPAddress.new(:ipv4 => '999.10.10.20')).not_to be_valid 127 | expect(IPAddress.new(:ipv4 => '2222.22.22.22')).not_to be_valid 128 | expect(IPAddress.new(:ipv4 => '22.2222.22.2')).not_to be_valid 129 | expect(IPAddress.new(:ipv4 => '127.0.0.1')).to be_valid 130 | expect(IPAddress.new(:ipv4 => '132.254.111.10')).to be_valid 131 | expect(IPAddress.new(:ipv4 => "132.254.111.10\n")).not_to be_valid 132 | end 133 | end 134 | 135 | # For clarification, NONE of the following numbers are real credit card numbers. 136 | # They only match the pattern. These were randomly made for testing. 137 | describe "credit_card" do 138 | class Client < TestActiveRecord 139 | attr_accessor :cc 140 | validates :cc, :credit_card => true 141 | end 142 | it "validates that the credit card number provided is valid" do 143 | expect(Client.new(:cc => '4264-2879-1230-0000')).to be_valid # Visa style 144 | expect(Client.new(:cc => '6011-1111-0000-2391')).to be_valid # Discover style 145 | expect(Client.new(:cc => '5422434400828888')).to be_valid # Mastercard style 146 | expect(Client.new(:cc => "5422434400828889\n")).not_to be_valid # Mastercard style 147 | expect(Client.new(:cc => '1233444444444444')).not_to be_valid # fake 148 | end 149 | end 150 | 151 | describe "ssn" do 152 | class AnotherPerson < TestActiveRecord 153 | attr_accessor :ssn 154 | validates :ssn, :ssn => true 155 | end 156 | it "validates that the social security number provided is valid" do 157 | expect(AnotherPerson.new(:ssn => "145.47.0191")).to be_valid 158 | expect(AnotherPerson.new(:ssn => "223-43-2343")).to be_valid 159 | expect(AnotherPerson.new(:ssn => "999.55.8888")).to be_valid 160 | expect(AnotherPerson.new(:ssn => "999.55.8888\n")).not_to be_valid 161 | expect(AnotherPerson.new(:ssn => "28934")).not_to be_valid 162 | expect(AnotherPerson.new(:ssn => "228934828934934")).not_to be_valid 163 | expect(AnotherPerson.new(:ssn => "23498.7234")).not_to be_valid 164 | end 165 | end 166 | 167 | describe "hex_color" do 168 | class Color < TestActiveRecord 169 | attr_accessor :color 170 | validates :color, :hex_color => true 171 | end 172 | it "validates that the hex color value provided is valid" do 173 | expect(Color.new(:color => "efefef")).to be_valid 174 | expect(Color.new(:color => "98de89")).to be_valid 175 | expect(Color.new(:color => "000011")).to be_valid 176 | expect(Color.new(:color => "132")).to be_valid 177 | expect(Color.new(:color => "eef")).to be_valid 178 | expect(Color.new(:color => "eef\n")).not_to be_valid 179 | expect(Color.new(:color => "efefe")).not_to be_valid 180 | expect(Color.new(:color => "zsdfsd")).not_to be_valid 181 | expect(Color.new(:color => "p98hul;")).not_to be_valid 182 | expect(Color.new(:color => "sdfsdfsf")).not_to be_valid 183 | end 184 | end 185 | 186 | describe "validation options" do 187 | class Phony < TestActiveRecord 188 | attr_accessor :phone, :phone2 189 | validates :phone, :us_phone => true, :on => :create 190 | validates :phone2, :us_phone => true, :on => :update 191 | end 192 | it "validates the phone formatting only on creation" do 193 | option = Phony.new(:phone => "(123) 234-4567") 194 | expect(option).to be_valid 195 | option.phone = "123123123" 196 | expect(option).to be_valid 197 | end 198 | 199 | class Iffy < TestActiveRecord 200 | attr_accessor :name, :phone 201 | validates_presence_of :name 202 | validates :phone, :us_phone => true, :if => lambda { |iffy| iffy.name == "Matthew" } 203 | end 204 | it "validates the phone formatting only if a name is specified" do 205 | expect(Iffy.new(:phone => "(123 345-4567", :name => "Bill")).to be_valid 206 | expect(Iffy.new(:phone => "(123 345-4567", :name => "Matthew")).not_to be_valid 207 | end 208 | 209 | class Unlessy < TestActiveRecord 210 | attr_accessor :name, :phone 211 | validates_presence_of :name 212 | validates :phone, :us_phone => true, :unless => lambda { |unlessy| unlessy.name == "Matthew" } 213 | end 214 | it "validates the phone formatting only if a name is specified" do 215 | expect(Unlessy.new(:phone => "(123 345-4567", :name => "Bill")).not_to be_valid 216 | expect(Unlessy.new(:phone => "(123 345-4567", :name => "Matthew")).to be_valid 217 | end 218 | end 219 | describe "dollars" do 220 | class Money < TestActiveRecord 221 | attr_accessor :amount 222 | validates :amount, :dollars => true 223 | end 224 | it "validates that the dollars amount provided is valid" do 225 | expect(Money.new(:amount => "$100.00")).to be_valid 226 | expect(Money.new(:amount => "100.00")).to be_valid 227 | expect(Money.new(:amount => "12,234,343")).to be_valid 228 | expect(Money.new(:amount => "$12.34")).to be_valid 229 | expect(Money.new(:amount => "120,123,232.32")).to be_valid 230 | expect(Money.new(:amount => "$$1111111100")).not_to be_valid 231 | expect(Money.new(:amount => "100;00")).not_to be_valid 232 | expect(Money.new(:amount => "238,3423,42..99")).not_to be_valid 233 | expect(Money.new(:amount => "$-233")).not_to be_valid 234 | end 235 | end 236 | describe "custom messages" do 237 | class Message < TestActiveRecord 238 | attr_accessor :first_name 239 | validates :first_name, :alpha => { :message => "is not a valid first name" } 240 | end 241 | it "are allowed and can be used in displaying error messages" do 242 | message = Message.new(:first_name => "invalid-first-name-123") 243 | expect(message).not_to be_valid 244 | expect(message.errors.keys.class).to eq Array 245 | expect(message.errors.full_messages.first).to match(/is not a valid first name/) 246 | end 247 | end 248 | 249 | describe "default error messages" do 250 | class Problems < TestActiveRecord 251 | attr_accessor :name 252 | validates :name, :alpha => true 253 | end 254 | it "set a default error" do 255 | problems = Problems.new(:name => "sdfs12312dfsd") 256 | expect(problems).not_to be_valid 257 | expect(problems.errors.full_messages.first).to match(/letters/i) 258 | email = Email.new(:email => "not.an.email.address") 259 | expect(email).not_to be_valid 260 | expect(email.errors.full_messages.first).to match(/email/i) 261 | end 262 | end 263 | 264 | describe "nil and blank values" do 265 | class PeopleTest < TestActiveRecord 266 | attr_accessor :email, :email2, :email3 267 | validates :email, :email => true, :allow_nil => true 268 | validates :email2, :email => true, :allow_blank => true 269 | validates :email3, :email => true 270 | end 271 | let(:people) { PeopleTest.new(:email => "mbridges.91@gmail.com", :email2 => "mbridges.91@gmail.com", :email3 => "mbridges.91@gmail.com") } 272 | it "should test nil and blank values correctly" do 273 | people.email = nil 274 | expect(people).to be_valid 275 | people.email = "mbridges.91@gmail.com" 276 | people.email2 = "" 277 | expect(people).to be_valid 278 | people.email2 = "mbridges.91@gmail.com" 279 | people.email3 = nil 280 | expect(people).not_to be_valid 281 | end 282 | end 283 | end 284 | end 285 | -------------------------------------------------------------------------------- /validates_formatting_of.gemspec: -------------------------------------------------------------------------------- 1 | # -*- encoding: utf-8 -*- 2 | require File.expand_path('../lib/validates_formatting_of/version', __FILE__) 3 | 4 | Gem::Specification.new do |gem| 5 | gem.authors = ["Matt Bridges"] 6 | gem.email = ["mbridges.91@gmail.com"] 7 | gem.description = %q{Common Rails validations wrapped in a gem.} 8 | gem.summary = %q{Adds several convenient methods to validate things such as emails, urls, and phone numbers in a Rails application} 9 | gem.homepage = "https://github.com/mattdbridges/validates_formatting_of" 10 | 11 | gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) } 12 | gem.files = `git ls-files`.split("\n") 13 | gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n") 14 | gem.name = "validates_formatting_of" 15 | gem.require_paths = ["lib"] 16 | gem.version = ValidatesFormattingOf::VERSION 17 | 18 | gem.add_dependency "activemodel" 19 | 20 | gem.add_development_dependency "rake" 21 | gem.add_development_dependency "rspec" 22 | gem.add_development_dependency "simplecov" 23 | gem.add_development_dependency "its" 24 | end 25 | --------------------------------------------------------------------------------