├── Gemfile ├── lib ├── tiny_validations │ └── version.rb └── tiny_validations.rb ├── Rakefile ├── .travis.yml ├── .gitignore ├── README.md ├── test ├── validations_test.rb └── test_helper.rb ├── LICENSE ├── tiny_validations.gemspec └── Gemfile.lock /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | gemspec -------------------------------------------------------------------------------- /lib/tiny_validations/version.rb: -------------------------------------------------------------------------------- 1 | module TinyValidations 2 | VERSION = 0.2 3 | end 4 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require "bundler/gem_tasks" 2 | require "rake/testtask" 3 | 4 | task :default => :test 5 | Rake::TestTask.new do |t| 6 | t.libs << "test" 7 | t.pattern = "test/**/*_test.rb" 8 | end 9 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: ruby 2 | rvm: 3 | - 2.0.0 4 | script: bundle exec rake test 5 | before_script: 6 | - psql -c 'create database tiny_validation_test;' -U postgres 7 | notifications: 8 | email: 9 | on_success: never 10 | on_failure: change 11 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.gem 2 | *.rbc 3 | *.sassc 4 | .sass-cache 5 | capybara-*.html 6 | .rspec 7 | .rvmrc 8 | /.bundle 9 | /vendor/bundle 10 | /log/* 11 | /tmp/* 12 | /db/*.sqlite3 13 | /public/system/* 14 | /coverage/ 15 | /spec/tmp/* 16 | **.orig 17 | rerun.txt 18 | pickle-email-*.html 19 | .project 20 | config/initializers/secret_token.rb 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Context Validations 2 | 3 | ## Get Started 4 | 5 | Add this line to your application’s Gemfile: 6 | 7 | ```ruby 8 | gem 'tiny_validations' 9 | ``` 10 | 11 | Add TinyValidations to models you want to add this. 12 | 13 | ```ruby 14 | class User < ActiveRecord::Base 15 | include TinyValidations 16 | 17 | validates :name, :email, presence: true 18 | 19 | validations_when_not [:email_subscription, :upgrading_account] do |model| 20 | model.validates :city, :state, :country, presence: true 21 | end 22 | 23 | validations_when :upgrading_account do |model| 24 | model.validates_presence_of :credit_card_number 25 | end 26 | end 27 | 28 | @user = user.new(name: 'Nando Sousa', email: 'nandosousafr@gmail.com') 29 | @user.valid?(:email_subscription) 30 | #=> true 31 | 32 | @user.valid?(:upgrading_account) 33 | #=> false 34 | 35 | @user.credit_card = '324324-242342-2342423-232423' 36 | @user.valid?(:upgrading_account) 37 | #=> true 38 | ``` 39 | -------------------------------------------------------------------------------- /test/validations_test.rb: -------------------------------------------------------------------------------- 1 | require_relative 'test_helper' 2 | 3 | class ValidationsTest < Minitest::Unit::TestCase 4 | 5 | def test_set_contexts 6 | assert @user.respond_to?(:context_validations_password_reset) 7 | assert @user.respond_to?(:context_validations_facebook_auth) 8 | assert @user.respond_to?(:context_validations_user_subscription) 9 | end 10 | 11 | def test_validations_when 12 | # context: :password_reset 13 | @user.valid?(:password_reset) 14 | assert_includes @user.errors, :password, 15 | 'password is not validating to :password_reset context' 16 | 17 | # context: :facebook_auth 18 | @user.valid?(:facebook_auth) 19 | assert_includes @user.errors, :fb_token_secret, 20 | 'fb_token_secredt is not validating to :facebook_auth context' 21 | end 22 | 23 | def test_validations_when_not 24 | # context: :password_reset 25 | @user.valid?(:password_reset) 26 | asserts_when_not 27 | 28 | # context: :user_subscription 29 | @user.valid?(:user_subscription) 30 | asserts_when_not 31 | end 32 | end 33 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Pixelbits 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /tiny_validations.gemspec: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | lib = File.expand_path('../lib', __FILE__) 3 | $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) 4 | require 'tiny_validations/version' 5 | 6 | Gem::Specification.new do |spec| 7 | spec.name = 'tiny_validations' 8 | spec.version = TinyValidations::VERSION 9 | spec.authors = ['Nando Sousa'] 10 | spec.email = ['nandosousafr@gmail.com'] 11 | spec.description = %q{Context Validations to Rails models} 12 | spec.summary = %q{Context Validations to Rails models} 13 | spec.homepage = 'https://github.com/pixelbits/tiny_validations' 14 | spec.license = 'MIT' 15 | 16 | spec.files = `git ls-files`.split($/) 17 | spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) } 18 | spec.test_files = spec.files.grep(%r{^(test|spec|features)/}) 19 | spec.require_paths = ['lib'] 20 | 21 | spec.add_development_dependency 'bundler' 22 | spec.add_development_dependency 'rake' 23 | spec.add_development_dependency 'minitest', '~> 4.7' 24 | spec.add_development_dependency 'sqlite3' 25 | spec.add_development_dependency 'rails' 26 | end 27 | 28 | -------------------------------------------------------------------------------- /lib/tiny_validations.rb: -------------------------------------------------------------------------------- 1 | require 'rails' 2 | require 'active_support' 3 | require 'active_record' 4 | 5 | module TinyValidations 6 | extend ActiveSupport::Concern 7 | 8 | def validations_when(key , &block) 9 | validations_base(key, &block) 10 | end 11 | 12 | def validations_when_not(key, &block) 13 | validations_base(key, :unless, &block) 14 | end 15 | 16 | def validations_base(rule, condition = :if, &block) 17 | if rule.is_a?(Array) 18 | keys = rule.map { |r| context_key(r) } 19 | else 20 | keys = Array(context_key(rule)) 21 | end 22 | 23 | options = {} 24 | options[condition] = -> { keys.include?(context_key(validation_context)) } 25 | 26 | instance_eval do 27 | keys.each { |k| attr_accessor k } 28 | with_options(options) { |validations| yield validations } 29 | end 30 | end 31 | 32 | def context=(key) 33 | if self.respond_to?(context_key(key)) 34 | self.validation_context = key 35 | else 36 | raise 'Context not found' 37 | end 38 | end 39 | 40 | private 41 | def context_key(key) 42 | "context_validations_#{key}".to_sym 43 | end 44 | end 45 | 46 | ActiveRecord::Base.send(:extend, TinyValidations) 47 | -------------------------------------------------------------------------------- /test/test_helper.rb: -------------------------------------------------------------------------------- 1 | require 'bundler/setup' 2 | Bundler.require(:default) 3 | require 'minitest/autorun' 4 | require 'minitest/pride' 5 | 6 | ENV['RACK_ENV'] = 'test' 7 | 8 | require 'active_record' 9 | 10 | # for debugging 11 | # ActiveRecord::Base.logger = Logger.new(STDOUT) 12 | 13 | # rails does this in activerecord/lib/active_record/railtie.rb 14 | ActiveRecord::Base.default_timezone = :utc 15 | ActiveRecord::Base.time_zone_aware_attributes = true 16 | 17 | # migrations 18 | ActiveRecord::Base.establish_connection :adapter => 'sqlite3', :database => 'tiny_validation_test' 19 | 20 | ActiveRecord::Migration.create_table :users, force: true do |t| 21 | t.string :name 22 | t.string :email 23 | t.string :city 24 | t.string :state 25 | t.string :password 26 | t.string :fb_token_secret 27 | 28 | t.timestamps 29 | end 30 | 31 | 32 | class User < ActiveRecord::Base 33 | include TinyValidations 34 | 35 | validates :name, :email, presence: true 36 | 37 | validations_when_not [:password_reset, :user_subscription] do |m| 38 | m.validates :city, :state, presence: true 39 | m.validates_inclusion_of :state, in: ['NY'] 40 | end 41 | 42 | validations_when :facebook_auth do |m| 43 | m.validates_presence_of :fb_token_secret 44 | end 45 | 46 | validations_when :password_reset do |m| 47 | m.validates :password, presence: true 48 | end 49 | end 50 | 51 | 52 | class Minitest::Unit::TestCase 53 | def setup 54 | User.destroy_all 55 | @user = User.new(name: 'Nando Sousa', 56 | email: 'nandosousafr@gmail.com') 57 | 58 | end 59 | 60 | def asserts_when_not 61 | refute_includes @user.errors, :city, 62 | 'city is validating to :password_reset_context' 63 | 64 | refute_includes @user.errors, :state, 65 | 'state is validating to :password_reset_context' 66 | end 67 | end 68 | 69 | -------------------------------------------------------------------------------- /Gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: . 3 | specs: 4 | tiny_validations (0.2) 5 | 6 | GEM 7 | remote: https://rubygems.org/ 8 | specs: 9 | actionmailer (4.0.3) 10 | actionpack (= 4.0.3) 11 | mail (~> 2.5.4) 12 | actionpack (4.0.3) 13 | activesupport (= 4.0.3) 14 | builder (~> 3.1.0) 15 | erubis (~> 2.7.0) 16 | rack (~> 1.5.2) 17 | rack-test (~> 0.6.2) 18 | activemodel (4.0.3) 19 | activesupport (= 4.0.3) 20 | builder (~> 3.1.0) 21 | activerecord (4.0.3) 22 | activemodel (= 4.0.3) 23 | activerecord-deprecated_finders (~> 1.0.2) 24 | activesupport (= 4.0.3) 25 | arel (~> 4.0.0) 26 | activerecord-deprecated_finders (1.0.3) 27 | activesupport (4.0.3) 28 | i18n (~> 0.6, >= 0.6.4) 29 | minitest (~> 4.2) 30 | multi_json (~> 1.3) 31 | thread_safe (~> 0.1) 32 | tzinfo (~> 0.3.37) 33 | arel (4.0.2) 34 | atomic (1.1.15) 35 | builder (3.1.4) 36 | erubis (2.7.0) 37 | hike (1.2.3) 38 | i18n (0.6.9) 39 | mail (2.5.4) 40 | mime-types (~> 1.16) 41 | treetop (~> 1.4.8) 42 | mime-types (1.25.1) 43 | minitest (4.7.5) 44 | multi_json (1.8.4) 45 | polyglot (0.3.4) 46 | rack (1.5.2) 47 | rack-test (0.6.2) 48 | rack (>= 1.0) 49 | rails (4.0.3) 50 | actionmailer (= 4.0.3) 51 | actionpack (= 4.0.3) 52 | activerecord (= 4.0.3) 53 | activesupport (= 4.0.3) 54 | bundler (>= 1.3.0, < 2.0) 55 | railties (= 4.0.3) 56 | sprockets-rails (~> 2.0.0) 57 | railties (4.0.3) 58 | actionpack (= 4.0.3) 59 | activesupport (= 4.0.3) 60 | rake (>= 0.8.7) 61 | thor (>= 0.18.1, < 2.0) 62 | rake (10.1.1) 63 | sprockets (2.11.0) 64 | hike (~> 1.2) 65 | multi_json (~> 1.0) 66 | rack (~> 1.0) 67 | tilt (~> 1.1, != 1.3.0) 68 | sprockets-rails (2.0.1) 69 | actionpack (>= 3.0) 70 | activesupport (>= 3.0) 71 | sprockets (~> 2.8) 72 | sqlite3 (1.3.7) 73 | thor (0.18.1) 74 | thread_safe (0.2.0) 75 | atomic (>= 1.1.7, < 2) 76 | tilt (1.4.1) 77 | treetop (1.4.15) 78 | polyglot 79 | polyglot (>= 0.3.1) 80 | tzinfo (0.3.38) 81 | 82 | PLATFORMS 83 | ruby 84 | 85 | DEPENDENCIES 86 | bundler 87 | minitest (~> 4.7) 88 | rails 89 | rake 90 | sqlite3 91 | tiny_validations! 92 | --------------------------------------------------------------------------------