Permalink
Browse files

initial commit

  • Loading branch information...
0 parents commit cabb744979a7dbf551fcd6f66d6e8a8658ae30f0 @adzap committed Feb 22, 2010
Showing with 393 additions and 0 deletions.
  1. +1 −0 .gitignore
  2. +20 −0 MIT-LICENSE
  3. +55 −0 README.rdoc
  4. +69 −0 Rakefile
  5. +30 −0 grouped_validations.gemspec
  6. +87 −0 lib/grouped_validations.rb
  7. +96 −0 spec/grouped_validations_spec.rb
  8. +35 −0 spec/spec_helper.rb
@@ -0,0 +1 @@
+pkg/*
@@ -0,0 +1,20 @@
+Copyright (c) 2010 Adam Meehan
+
+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:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+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.
@@ -0,0 +1,55 @@
+= Grouped Validations
+
+Allows you to define validation groups in ActiveRecord for more control over what validations you want to run.
+
+This can be useful for multi-page forms or wizard style data entry.
+
+Works with Rails 2.3.5 and probably earlier. Haven't tried it with Rails 3 yet.
+
+== Installation
+
+Just install the gem
+
+ gem install grouped_validations
+
+Add it to your Rails environment gems
+
+ config.gem 'grouped_validations'
+
+== Usage
+
+Define validations as you would normally but inside a validation_group block which you pass a group
+name to.
+
+ class Person < ActiveRecord::Base
+ validation_group :name do
+ validates_presence_of :first_name
+ validates_presence_of :last_name
+ end
+
+ validates_presence_of :sex
+ end
+
+You can define validations outside the group as normal.
+
+To check for errors for only a certain group of validations
+
+ p = Person.new
+ p.group_valid?(:name) # => false
+ p.first_name = 'John'
+ p.last_name = 'Smith'
+ p.group_valid?(:name) # => true
+
+If you run the normal valid? method all validations, inside and outside validation groups, will be run.
+
+ p.valid? # => false because sex is not present
+
+You can also check validation for multiple groups
+
+ p.groups_valid?(:group1, :group2)
+
+== Credits
+
+* Adam Meehan (http://github.com/adzap)
+
+Copyright (c) 2010 Adam Meehan, released under the MIT license
@@ -0,0 +1,69 @@
+require 'rubygems'
+require 'rake/rdoctask'
+require 'rake/gempackagetask'
+require 'rubygems/specification'
+require 'spec/rake/spectask'
+
+GEM_NAME = "grouped_validations"
+GEM_VERSION = '0.1.0'
+
+spec = Gem::Specification.new do |s|
+ s.name = GEM_NAME
+ s.version = GEM_VERSION
+ s.platform = Gem::Platform::RUBY
+ s.rubyforge_project = GEM_NAME
+ s.has_rdoc = true
+ s.extra_rdoc_files = ["README.rdoc"]
+ s.summary = "Define validation groups in ActiveRecord for greater control over which validations to run."
+ s.description = s.summary
+ s.author = "Adam Meehan"
+ s.email = "adam.meehan@gmail.com"
+ s.homepage = "http://github.com/adzap/grouped_validations"
+
+ s.require_path = 'lib'
+ s.autorequire = GEM_NAME
+ s.files = %w(MIT-LICENSE README.rdoc Rakefile) + Dir.glob("{lib,spec}/**/*")
+end
+
+desc 'Default: run specs.'
+task :default => :spec
+
+spec_files = Rake::FileList["spec/**/*_spec.rb"]
+
+desc "Run specs"
+Spec::Rake::SpecTask.new do |t|
+ t.spec_files = spec_files
+ t.spec_opts = ["-c"]
+end
+
+desc "Generate code coverage"
+Spec::Rake::SpecTask.new(:coverage) do |t|
+ t.spec_files = spec_files
+ t.rcov = true
+ t.rcov_opts = ['--exclude', 'spec,/var/lib/gems']
+end
+
+desc 'Generate documentation for plugin.'
+Rake::RDocTask.new(:rdoc) do |rdoc|
+ rdoc.rdoc_dir = 'rdoc'
+ rdoc.title = 'GroupedValidations'
+ rdoc.options << '--line-numbers' << '--inline-source'
+ rdoc.rdoc_files.include('README')
+ rdoc.rdoc_files.include('lib/**/*.rb')
+end
+
+Rake::GemPackageTask.new(spec) do |pkg|
+ pkg.gem_spec = spec
+end
+
+desc "install the gem locally"
+task :install => [:package] do
+ sh %{gem install pkg/#{GEM_NAME}-#{GEM_VERSION}}
+end
+
+desc "create a gemspec file"
+task :make_spec do
+ File.open("#{GEM_NAME}.gemspec", "w") do |file|
+ file.puts spec.to_ruby
+ end
+end
@@ -0,0 +1,30 @@
+# -*- encoding: utf-8 -*-
+
+Gem::Specification.new do |s|
+ s.name = %q{grouped_validations}
+ s.version = "0.1.0"
+
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
+ s.authors = ["Adam Meehan"]
+ s.autorequire = %q{grouped_validations}
+ s.date = %q{2010-02-22}
+ s.description = %q{Define validation groups in ActiveRecord for greater control over which validations to run.}
+ s.email = %q{adam.meehan@gmail.com}
+ s.extra_rdoc_files = ["README.rdoc"]
+ s.files = ["MIT-LICENSE", "README.rdoc", "Rakefile", "lib/grouped_validations.rb", "spec/grouped_validations_spec.rb", "spec/spec_helper.rb"]
+ s.homepage = %q{http://github.com/adzap/grouped_validations}
+ s.require_paths = ["lib"]
+ s.rubyforge_project = %q{grouped_validations}
+ s.rubygems_version = %q{1.3.5}
+ s.summary = %q{Define validation groups in ActiveRecord for greater control over which validations to run.}
+
+ if s.respond_to? :specification_version then
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
+ s.specification_version = 3
+
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
+ else
+ end
+ else
+ end
+end
@@ -0,0 +1,87 @@
+module GroupedValidations
+
+ def self.included(base)
+ base.extend ClassMethods
+ base.class_eval do
+ include InstanceMethods
+ class_inheritable_accessor :validation_groups
+ alias_method_chain :valid?, :groups
+ class << self
+ alias_method_chain :validation_method, :groups
+ end
+ end
+ end
+
+ module ClassMethods
+
+ def validation_group(name, &block)
+ raise "The validation_group method requires a block" unless block_given?
+
+ self.validation_groups ||= []
+ self.validation_groups << name
+
+ base_name = :"validate_#{name}"
+ define_callbacks base_name, :"#{base_name}_on_create", :"#{base_name}_on_update"
+
+ @current_validation_group = name
+ class_eval &block
+ @current_validation_group = nil
+ end
+
+ def validation_method_with_groups(on)
+ if @current_validation_group
+ base_name = :"validate_#{@current_validation_group}"
+ case on
+ when :save then base_name
+ when :create then :"#{base_name}_on_create"
+ when :update then :"#{base_name}_on_update"
+ end
+ else
+ validation_method_without_groups on
+ end
+ end
+
+ end
+
+ module InstanceMethods
+
+ def group_valid?(name)
+ raise "Validation group '#{name}' not defined" unless validation_groups.include?(name)
+
+ errors.clear
+ run_group_validation_callbacks name
+ errors.empty?
+ end
+
+ def groups_valid?(*groups)
+ errors.clear
+ groups.each do |name|
+ raise "Validation group '#{name}' not defined" unless validation_groups.include?(name)
+ run_group_validation_callbacks name
+ end
+ errors.empty?
+ end
+
+ def valid_with_groups?
+ valid_without_groups?
+ (validation_groups || []).each do |group|
+ run_group_validation_callbacks group
+ end
+ errors.empty?
+ end
+
+ def run_group_validation_callbacks(name)
+ base_name = :"validate_#{name}"
+ run_callbacks(base_name)
+ if new_record?
+ run_callbacks(:"#{base_name}_on_create")
+ else
+ run_callbacks(:"#{base_name}_on_update")
+ end
+ end
+
+ end
+
+end
+
+ActiveRecord::Base.send :include, GroupedValidations
@@ -0,0 +1,96 @@
+require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
+
+describe GroupedValidations do
+ before do
+ reset_class Person
+ end
+
+ it "should add validation_group class method" do
+ Person.should respond_to(:validation_group)
+ end
+
+ it "should store defined validation group names" do
+ Person.validation_group(:dummy) { }
+ Person.validation_groups.should == [:dummy]
+ end
+
+ it "it should add group_valid? method which takes a group name param" do
+ Person.validation_group(:dummy) { }
+ p = Person.new
+ p.group_valid?(:dummy)
+ end
+
+ it "should raise exception if valiation group not defined on group_valid check" do
+ p = Person.new
+ lambda { p.group_valid?(:dummy) }.should raise_exception
+ end
+
+ it "should run the validations defined inside the validation group" do
+ Person.validation_group :name do
+ validates_presence_of :first_name
+ validates_presence_of :last_name
+ end
+
+ p = Person.new
+ p.group_valid?(:name)
+ p.should have(2).errors
+
+ p.first_name = 'Dave'
+ p.last_name = 'Smith'
+ p.group_valid?(:name)
+ p.should have(0).errors
+ end
+
+ it "should run all validation groups passed to groups_valid?" do
+ Person.class_eval do
+ validation_group :first_name_group do
+ validates_presence_of :first_name
+ end
+ validation_group :last_name_group do
+ validates_presence_of :last_name
+ end
+ end
+
+ p = Person.new
+ p.groups_valid?(:first_name_group, :last_name_group)
+ p.should have(2).errors
+ end
+
+ it "should run all validation including groups when valid? method called" do
+ Person.class_eval do
+ validation_group :first_name_group do
+ validates_presence_of :first_name
+ end
+ validation_group :last_name_group do
+ validates_presence_of :last_name
+ end
+
+ validates_presence_of :sex
+ end
+
+ p = Person.new
+ p.valid?
+ p.should have(3).errors
+ end
+
+ it "should respect :on validation option" do
+ Person.validation_group :name do
+ validates_presence_of :first_name, :on => :create
+ validates_presence_of :last_name, :on => :update
+ end
+
+ p = Person.new
+ p.group_valid?(:name)
+ p.should have(1).errors
+ p.first_name = 'Dave'
+ p.group_valid?(:name)
+ p.should have(0).errors
+
+ p.save.should be_true
+ p.group_valid?(:name)
+ p.should have(1).errors
+ p.last_name = 'Smith'
+ p.group_valid?(:name)
+ p.should have(0).errors
+ end
+end
Oops, something went wrong.

0 comments on commit cabb744

Please sign in to comment.