grouped_validations 0.2.2 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Gemfile +7 -0
- data/Gemfile.lock +37 -0
- data/README.rdoc +80 -3
- data/Rakefile +7 -51
- data/grouped_validations.gemspec +23 -0
- data/init.rb +1 -0
- data/lib/grouped_validations.rb +65 -33
- data/lib/grouped_validations/active_model.rb +21 -30
- data/lib/grouped_validations/version.rb +1 -1
- data/spec/grouped_validations_spec.rb +213 -92
- data/spec/spec_helper.rb +12 -16
- metadata +16 -12
- data/lib/grouped_validations/active_record.rb +0 -47
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
GEM
|
2
|
+
remote: http://rubygems.org/
|
3
|
+
specs:
|
4
|
+
activemodel (3.0.1)
|
5
|
+
activesupport (= 3.0.1)
|
6
|
+
builder (~> 2.1.2)
|
7
|
+
i18n (~> 0.4.1)
|
8
|
+
activesupport (3.0.1)
|
9
|
+
builder (2.1.2)
|
10
|
+
columnize (0.3.1)
|
11
|
+
diff-lcs (1.1.2)
|
12
|
+
i18n (0.4.2)
|
13
|
+
linecache (0.43)
|
14
|
+
rspec (2.0.1)
|
15
|
+
rspec-core (~> 2.0.1)
|
16
|
+
rspec-expectations (~> 2.0.1)
|
17
|
+
rspec-mocks (~> 2.0.1)
|
18
|
+
rspec-core (2.0.1)
|
19
|
+
rspec-expectations (2.0.1)
|
20
|
+
diff-lcs (>= 1.1.2)
|
21
|
+
rspec-mocks (2.0.1)
|
22
|
+
rspec-core (~> 2.0.1)
|
23
|
+
rspec-expectations (~> 2.0.1)
|
24
|
+
ruby-debug (0.10.3)
|
25
|
+
columnize (>= 0.1)
|
26
|
+
ruby-debug-base (~> 0.10.3.0)
|
27
|
+
ruby-debug-base (0.10.3)
|
28
|
+
linecache (>= 0.3)
|
29
|
+
|
30
|
+
PLATFORMS
|
31
|
+
ruby
|
32
|
+
|
33
|
+
DEPENDENCIES
|
34
|
+
activemodel (~> 3.0.0)
|
35
|
+
activesupport (~> 3.0.0)
|
36
|
+
rspec (~> 2.0.0)
|
37
|
+
ruby-debug
|
data/README.rdoc
CHANGED
@@ -1,10 +1,12 @@
|
|
1
1
|
= Grouped Validations
|
2
2
|
|
3
|
-
Allows you to define validation groups
|
3
|
+
Allows you to define ActiveModel validation groups for more control over what validations you want to run.
|
4
4
|
|
5
5
|
This can be useful for multi-page forms or wizard style data entry.
|
6
6
|
|
7
|
-
Works with Rails
|
7
|
+
Works with Rails 3.
|
8
|
+
|
9
|
+
For Rails 2.x support, try version 0.2.2.
|
8
10
|
|
9
11
|
== Installation
|
10
12
|
|
@@ -16,6 +18,7 @@ Add it to your Rails environment gems
|
|
16
18
|
|
17
19
|
config.gem 'grouped_validations'
|
18
20
|
|
21
|
+
|
19
22
|
== Usage
|
20
23
|
|
21
24
|
Define validations as you would normally but inside a validation_group block which you pass a group
|
@@ -62,8 +65,82 @@ To define validation blocks just use the respective group validation method, lik
|
|
62
65
|
validate_name_on_update {|r| # something custom on update }
|
63
66
|
end
|
64
67
|
|
68
|
+
|
69
|
+
== Group Options
|
70
|
+
|
71
|
+
You can use a validation group like similar to the with_options method, but for validation methods only.
|
72
|
+
|
73
|
+
If you pass in an options hash, those options will be applied to each valiation method in the block.
|
74
|
+
|
75
|
+
validation_group :name, :if => :ready? do
|
76
|
+
validates_presence_of :first_name
|
77
|
+
validates_presence_of :last_name
|
78
|
+
end
|
79
|
+
|
80
|
+
Which effectively the same as doing the following:
|
81
|
+
|
82
|
+
validates_presence_of :first_name, :if => :ready?
|
83
|
+
validates_presence_of :last_name, :if => :ready?
|
84
|
+
|
85
|
+
If you set an option for a specific validation method, it will not be overriden with the validation group
|
86
|
+
options.
|
87
|
+
|
88
|
+
validation_group :name, :if => :ready? do
|
89
|
+
validates_presence_of :first_name
|
90
|
+
validates_presence_of :last_name, :if => {|r| !r.popstar? }
|
91
|
+
end
|
92
|
+
|
93
|
+
The last_name attribute will be required unless the person is a popstar.
|
94
|
+
|
95
|
+
The options should work for any validation method which calls the validate class method internally. This includes
|
96
|
+
all the default validations.
|
97
|
+
|
98
|
+
For more precision on when to merge the groups options you can pass an argument to the block and use it like a
|
99
|
+
with_options call. Then only those validation methods call on the argument will have the options merged in.
|
100
|
+
|
101
|
+
validation_group :name, :if => :ready? do |options|
|
102
|
+
# Options merged
|
103
|
+
options.validates_presence_of :first_name
|
104
|
+
|
105
|
+
# No options merged
|
106
|
+
validates_presence_of :last_name
|
107
|
+
end
|
108
|
+
|
109
|
+
|
110
|
+
== Grouped Errors
|
111
|
+
|
112
|
+
The errors for the model can be returned as hash with the group names as the keys. If you have a number of groups
|
113
|
+
you can deal with the error messages in specific ways per group.
|
114
|
+
|
115
|
+
validation_group :name do
|
116
|
+
validates_presence_of :first_name
|
117
|
+
validates_presence_of :last_name
|
118
|
+
end
|
119
|
+
|
120
|
+
validates_presence_of :sex
|
121
|
+
|
122
|
+
To access all errors outside of a validation group, use nil as the key:
|
123
|
+
|
124
|
+
person.grouped_errors[nil]
|
125
|
+
|
126
|
+
Use the group name as the key for all errors in that group:
|
127
|
+
|
128
|
+
person.grouped_errors[:name]
|
129
|
+
|
130
|
+
Be aware that the validations will all be run. If you have just called <tt>valid?</tt> then the same validations will be run
|
131
|
+
again and the current state of the object is used. This is for consideration if the validations are expensive, time
|
132
|
+
sensitive or you have changed the object after calling <tt>valid?</tt>.
|
133
|
+
|
134
|
+
You can use the <tt>grouped_errors</tt> method instead of <tt>valid?</tt> to check on a valid object like so:
|
135
|
+
|
136
|
+
# Validations all run
|
137
|
+
if person.grouped_errors.empty?
|
138
|
+
# object is valid
|
139
|
+
end
|
140
|
+
|
141
|
+
|
65
142
|
== Credits
|
66
143
|
|
67
144
|
* Adam Meehan (http://github.com/adzap)
|
68
145
|
|
69
|
-
Copyright (c) 2010 Adam Meehan, released under the MIT license
|
146
|
+
Copyright (c) 2010-2011 Adam Meehan, released under the MIT license
|
data/Rakefile
CHANGED
@@ -1,47 +1,19 @@
|
|
1
|
-
require '
|
2
|
-
|
3
|
-
require 'rake/gempackagetask'
|
4
|
-
require 'rubygems/specification'
|
5
|
-
require 'spec/rake/spectask'
|
6
|
-
require 'lib/grouped_validations/version'
|
7
|
-
|
8
|
-
GEM_NAME = "grouped_validations"
|
9
|
-
GEM_VERSION = GroupedValidations::VERSION
|
1
|
+
require 'bundler'
|
2
|
+
Bundler::GemHelper.install_tasks
|
10
3
|
|
11
|
-
|
12
|
-
|
13
|
-
s.version = GEM_VERSION
|
14
|
-
s.platform = Gem::Platform::RUBY
|
15
|
-
s.rubyforge_project = GEM_NAME
|
16
|
-
s.has_rdoc = true
|
17
|
-
s.extra_rdoc_files = ["README.rdoc"]
|
18
|
-
s.summary = "Define validation groups in ActiveRecord for greater control over which validations to run."
|
19
|
-
s.description = s.summary
|
20
|
-
s.author = "Adam Meehan"
|
21
|
-
s.email = "adam.meehan@gmail.com"
|
22
|
-
s.homepage = "http://github.com/adzap/grouped_validations"
|
23
|
-
|
24
|
-
s.require_path = 'lib'
|
25
|
-
s.autorequire = GEM_NAME
|
26
|
-
s.files = %w(MIT-LICENSE README.rdoc Rakefile) + Dir.glob("{lib,spec}/**/*")
|
27
|
-
end
|
4
|
+
require 'rake/rdoctask'
|
5
|
+
require 'rspec/core/rake_task'
|
28
6
|
|
29
7
|
desc 'Default: run specs.'
|
30
8
|
task :default => :spec
|
31
9
|
|
32
|
-
spec_files = Rake::FileList["spec/**/*_spec.rb"]
|
33
|
-
|
34
10
|
desc "Run specs"
|
35
|
-
|
36
|
-
t.spec_files = spec_files
|
37
|
-
t.spec_opts = ["-c"]
|
38
|
-
end
|
11
|
+
RSpec::Core::RakeTask.new(:spec)
|
39
12
|
|
40
13
|
desc "Generate code coverage"
|
41
|
-
|
42
|
-
t.spec_files = spec_files
|
14
|
+
RSpec::Core::RakeTask.new(:coverage) do |t|
|
43
15
|
t.rcov = true
|
44
|
-
t.rcov_opts = ['--exclude', 'spec
|
16
|
+
t.rcov_opts = ['--exclude', 'spec']
|
45
17
|
end
|
46
18
|
|
47
19
|
desc 'Generate documentation for plugin.'
|
@@ -52,19 +24,3 @@ Rake::RDocTask.new(:rdoc) do |rdoc|
|
|
52
24
|
rdoc.rdoc_files.include('README')
|
53
25
|
rdoc.rdoc_files.include('lib/**/*.rb')
|
54
26
|
end
|
55
|
-
|
56
|
-
Rake::GemPackageTask.new(spec) do |pkg|
|
57
|
-
pkg.gem_spec = spec
|
58
|
-
end
|
59
|
-
|
60
|
-
desc "install the gem locally"
|
61
|
-
task :install => [:package] do
|
62
|
-
sh %{gem install pkg/#{GEM_NAME}-#{GEM_VERSION}}
|
63
|
-
end
|
64
|
-
|
65
|
-
desc "create a gemspec file"
|
66
|
-
task :make_spec do
|
67
|
-
File.open("#{GEM_NAME}.gemspec", "w") do |file|
|
68
|
-
file.puts spec.to_ruby
|
69
|
-
end
|
70
|
-
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
$:.push File.expand_path("../lib", __FILE__)
|
4
|
+
require "grouped_validations/version"
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{grouped_validations}
|
8
|
+
s.version = GroupedValidations::VERSION
|
9
|
+
s.platform = Gem::Platform::RUBY
|
10
|
+
s.authors = ["Adam Meehan"]
|
11
|
+
s.email = %q{adam.meehan@gmail.com}
|
12
|
+
s.homepage = %q{http://github.com/adzap/grouped_validations}
|
13
|
+
s.summary = %q{Define validation groups in a model for greater control over which validations are run.}
|
14
|
+
s.description = s.summary
|
15
|
+
|
16
|
+
s.rubyforge_project = %q{grouped_validations}
|
17
|
+
|
18
|
+
s.files = `git ls-files`.split("\n") - %w{ .gitignore .rspec autotest }
|
19
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
20
|
+
s.extra_rdoc_files = ["README.rdoc"]
|
21
|
+
s.require_paths = ["lib"]
|
22
|
+
s.autorequire = %q{grouped_validations}
|
23
|
+
end
|
data/init.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'grouped_validations'
|
data/lib/grouped_validations.rb
CHANGED
@@ -1,61 +1,93 @@
|
|
1
|
+
require 'active_model/validations'
|
2
|
+
require 'grouped_validations/active_model'
|
3
|
+
|
1
4
|
module GroupedValidations
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
included do
|
8
|
+
class_attribute :validation_groups
|
9
|
+
self.validation_groups = []
|
10
|
+
end
|
2
11
|
|
3
12
|
module ClassMethods
|
4
13
|
|
5
|
-
def
|
6
|
-
|
14
|
+
def validate(*args, &block)
|
15
|
+
return super unless @_current_validation_group
|
7
16
|
|
8
|
-
|
9
|
-
|
17
|
+
options = args.extract_options!.dup
|
18
|
+
unless @_current_validation_group[:with_options]
|
19
|
+
options.reverse_merge!(@_current_validation_group.except(:name))
|
10
20
|
end
|
11
21
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
22
|
+
if options.key?(:on)
|
23
|
+
options = options.dup
|
24
|
+
options[:if] = Array.wrap(options[:if])
|
25
|
+
options[:if] << "validation_context == :#{options[:on]}"
|
26
|
+
end
|
27
|
+
args << options
|
28
|
+
set_callback(:"validate_#{@_current_validation_group[:name]}", *args, &block)
|
29
|
+
end
|
16
30
|
|
17
|
-
|
18
|
-
|
19
|
-
@current_validation_group = nil
|
31
|
+
def _define_group_validation_callbacks(group)
|
32
|
+
define_callbacks :"validate_#{group}", :scope => 'validate'
|
20
33
|
end
|
21
34
|
|
22
35
|
end
|
23
36
|
|
24
37
|
module InstanceMethods
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
alias_method_chain :validation_method, :groups
|
31
|
-
else
|
32
|
-
alias_method_chain :validate, :groups
|
33
|
-
end
|
34
|
-
end
|
38
|
+
|
39
|
+
def valid?(context=nil)
|
40
|
+
super
|
41
|
+
validation_groups.each do |group|
|
42
|
+
_run_group_validation_callbacks(group, context)
|
35
43
|
end
|
44
|
+
errors.empty?
|
36
45
|
end
|
37
46
|
|
38
47
|
def groups_valid?(*groups)
|
48
|
+
options = groups.extract_options!
|
39
49
|
errors.clear
|
40
50
|
groups.each do |group|
|
41
51
|
raise "Validation group '#{group}' not defined" unless validation_groups.include?(group)
|
42
|
-
|
52
|
+
_run_group_validation_callbacks(group, options[:context])
|
43
53
|
end
|
44
54
|
errors.empty?
|
45
55
|
end
|
46
|
-
|
56
|
+
alias_method :group_valid?, :groups_valid?
|
47
57
|
|
48
|
-
|
58
|
+
def grouped_errors(context=nil)
|
59
|
+
original_errors = @errors.dup if @errors
|
60
|
+
@errors = nil
|
61
|
+
grouped = {}
|
49
62
|
|
50
|
-
|
63
|
+
with_validation_context(context) do
|
64
|
+
_run_validate_callbacks
|
65
|
+
grouped[nil] = @errors
|
51
66
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
67
|
+
validation_groups.each do |group|
|
68
|
+
@errors = nil
|
69
|
+
send(:"_run_validate_#{group}_callbacks")
|
70
|
+
grouped[group] = @errors
|
71
|
+
end
|
72
|
+
end
|
73
|
+
grouped.values.all?(&:empty?) ? {} : grouped
|
74
|
+
ensure
|
75
|
+
@errors = original_errors
|
76
|
+
end
|
77
|
+
|
78
|
+
def _run_group_validation_callbacks(group, context=nil)
|
79
|
+
with_validation_context(context) do
|
80
|
+
send(:"_run_validate_#{group}_callbacks")
|
81
|
+
end
|
82
|
+
end
|
56
83
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
84
|
+
def with_validation_context(context)
|
85
|
+
context ||= (persisted? ? :update : :create)
|
86
|
+
current_context, self.validation_context = validation_context, context
|
87
|
+
yield
|
88
|
+
ensure
|
89
|
+
self.validation_context = current_context
|
90
|
+
end
|
91
|
+
|
92
|
+
end
|
61
93
|
end
|
@@ -1,43 +1,34 @@
|
|
1
|
-
module
|
1
|
+
module ActiveModel
|
2
|
+
module Validations
|
2
3
|
|
3
|
-
|
4
|
+
module ClassMethods
|
4
5
|
|
5
|
-
|
6
|
-
|
7
|
-
end
|
6
|
+
def validation_group(group, options={}, &block)
|
7
|
+
raise "The validation_group method requires a block" unless block_given?
|
8
8
|
|
9
|
-
|
10
|
-
|
11
|
-
options = args.last
|
12
|
-
if options.is_a?(Hash) && options.key?(:on)
|
13
|
-
options[:if] = Array(options[:if])
|
14
|
-
options[:if] << "self.validation_context == :#{options[:on]}"
|
9
|
+
unless include?(GroupedValidations)
|
10
|
+
include GroupedValidations
|
15
11
|
end
|
16
|
-
set_callback(:"validate_#{@current_validation_group}", *args, &block)
|
17
|
-
else
|
18
|
-
validate_without_groups(*args, &block)
|
19
|
-
end
|
20
|
-
end
|
21
12
|
|
22
|
-
|
13
|
+
self.validation_groups += [ group ]
|
23
14
|
|
24
|
-
|
15
|
+
_define_group_validation_callbacks(group)
|
25
16
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
17
|
+
options[:name] = group
|
18
|
+
|
19
|
+
if block.arity == 1
|
20
|
+
@_current_validation_group = options.merge(:with_options => true)
|
21
|
+
with_options(options.except(:name)) do |config|
|
22
|
+
yield config
|
23
|
+
end
|
24
|
+
else
|
25
|
+
@_current_validation_group = options
|
26
|
+
yield
|
27
|
+
end
|
28
|
+
@_current_validation_group = nil
|
30
29
|
end
|
31
|
-
errors.empty?
|
32
|
-
end
|
33
30
|
|
34
|
-
def run_group_validation_callbacks(group)
|
35
|
-
current_context, self.validation_context = validation_context, (new_record? ? :create : :update)
|
36
|
-
send(:"_run_validate_#{group}_callbacks")
|
37
|
-
ensure
|
38
|
-
self.validation_context = current_context
|
39
31
|
end
|
40
32
|
|
41
33
|
end
|
42
|
-
|
43
34
|
end
|
@@ -1,6 +1,8 @@
|
|
1
|
-
require
|
1
|
+
require 'spec_helper'
|
2
2
|
|
3
3
|
describe GroupedValidations do
|
4
|
+
let(:person) { Person.new }
|
5
|
+
|
4
6
|
before do
|
5
7
|
reset_class Person
|
6
8
|
end
|
@@ -9,123 +11,242 @@ describe GroupedValidations do
|
|
9
11
|
Person.should respond_to(:validation_group)
|
10
12
|
end
|
11
13
|
|
12
|
-
|
13
|
-
|
14
|
-
|
14
|
+
describe ".validation_group" do
|
15
|
+
it "should store defined validation group names" do
|
16
|
+
Person.class_eval do
|
17
|
+
validation_group(:dummy) { }
|
18
|
+
end
|
19
|
+
Person.validation_groups.should == [:dummy]
|
20
|
+
end
|
15
21
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
22
|
+
it "it should add group_valid? method which takes a group name param" do
|
23
|
+
Person.class_eval do
|
24
|
+
validation_group(:dummy) { }
|
25
|
+
end
|
26
|
+
|
27
|
+
person.group_valid?(:dummy)
|
28
|
+
end
|
20
29
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
30
|
+
context "with options" do
|
31
|
+
context "as implicit block" do
|
32
|
+
it 'should pass options for group to validations' do
|
33
|
+
Person.class_eval do
|
34
|
+
validation_group(:name, :if => lambda {|r| r.last_name.nil? }) do
|
35
|
+
validates_presence_of :first_name
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
person.group_valid?(:name)
|
40
|
+
person.should have(1).errors
|
41
|
+
|
42
|
+
person.last_name = 'smith'
|
43
|
+
person.group_valid?(:name)
|
44
|
+
person.should have(0).errors
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'should not override explicit validation method options' do
|
48
|
+
Person.class_eval do
|
49
|
+
validation_group(:name, :if => lambda { true }) do
|
50
|
+
validates_presence_of :first_name, :if => lambda { false }
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
person.group_valid?(:name)
|
55
|
+
person.should have(0).errors
|
56
|
+
end
|
57
|
+
end
|
26
58
|
|
27
|
-
|
28
|
-
|
29
|
-
|
59
|
+
context "as block argument" do
|
60
|
+
it 'should pass options for group to validations' do
|
61
|
+
Person.class_eval do
|
62
|
+
validation_group(:name, :if => lambda {|r| r.last_name.nil? }) do |options|
|
63
|
+
options.validates_presence_of :first_name
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
person.group_valid?(:name)
|
68
|
+
person.should have(1).errors
|
69
|
+
|
70
|
+
person.last_name = 'smith'
|
71
|
+
person.group_valid?(:name)
|
72
|
+
person.should have(0).errors
|
73
|
+
end
|
74
|
+
|
75
|
+
it 'should not override explicit options' do
|
76
|
+
Person.class_eval do
|
77
|
+
validation_group(:name, :if => lambda {|r| r.last_name.nil? }) do |options|
|
78
|
+
options.validates_presence_of :first_name, :if => lambda { false }
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
person.group_valid?(:name)
|
83
|
+
person.should have(0).errors
|
84
|
+
end
|
85
|
+
|
86
|
+
it 'should not apply options to validations methods not using block argument' do
|
87
|
+
Person.class_eval do
|
88
|
+
validation_group(:name, :if => lambda { false }) do |options|
|
89
|
+
options.validates_presence_of :first_name
|
90
|
+
validates_presence_of :last_name
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
person.group_valid?(:name)
|
95
|
+
person.errors[:first_name].should be_empty
|
96
|
+
person.errors[:last_name].should_not be_empty
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
30
100
|
end
|
31
101
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
102
|
+
describe "#group_valid?" do
|
103
|
+
it "should run the validations defined inside the validation group" do
|
104
|
+
Person.class_eval do
|
105
|
+
validation_group :name do
|
106
|
+
validates_presence_of :first_name
|
107
|
+
validates_presence_of :last_name
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
person.group_valid?(:name)
|
112
|
+
person.should have(2).errors
|
113
|
+
|
114
|
+
person.first_name = 'Dave'
|
115
|
+
person.last_name = 'Smith'
|
116
|
+
person.group_valid?(:name)
|
117
|
+
person.should have(0).errors
|
36
118
|
end
|
37
119
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
p.first_name = 'Dave'
|
43
|
-
p.last_name = 'Smith'
|
44
|
-
p.group_valid?(:name)
|
45
|
-
p.should have(0).errors
|
46
|
-
end
|
120
|
+
it "should raise exception if valiation group not defined" do
|
121
|
+
expect { person.group_valid?(:dummy) }.should raise_exception
|
122
|
+
end
|
47
123
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
124
|
+
it "should run all validation groups passed to groups_valid?" do
|
125
|
+
Person.class_eval do
|
126
|
+
validation_group :first_name_group do
|
127
|
+
validates_presence_of :first_name
|
128
|
+
end
|
129
|
+
validation_group :last_name_group do
|
130
|
+
validates_presence_of :last_name
|
131
|
+
end
|
55
132
|
end
|
133
|
+
|
134
|
+
person.groups_valid?(:first_name_group, :last_name_group)
|
135
|
+
person.should have(2).errors
|
56
136
|
end
|
57
137
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
138
|
+
context "with validation context" do
|
139
|
+
it "should run only validations for explicit context" do
|
140
|
+
Person.class_eval do
|
141
|
+
validation_group :name do
|
142
|
+
validates_presence_of :last_name, :on => :update
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
person.persisted = false
|
147
|
+
person.last_name = nil
|
148
|
+
person.group_valid?(:name, :context => :create)
|
149
|
+
person.should have(0).errors
|
150
|
+
|
151
|
+
person.persisted = true
|
152
|
+
person.group_valid?(:name, :context => :update)
|
153
|
+
person.should have(1).errors
|
154
|
+
|
155
|
+
person.last_name = 'Smith'
|
156
|
+
person.group_valid?(:name)
|
157
|
+
person.should have(0).errors
|
67
158
|
end
|
68
|
-
|
69
|
-
|
159
|
+
|
160
|
+
it "should run only validations for implicit model context" do
|
161
|
+
Person.class_eval do
|
162
|
+
validation_group :name do
|
163
|
+
validates_presence_of :first_name, :on => :create
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
person.persisted = false
|
168
|
+
person.group_valid?(:name)
|
169
|
+
person.should have(1).errors
|
170
|
+
|
171
|
+
person.first_name = 'Dave'
|
172
|
+
person.group_valid?(:name)
|
173
|
+
person.should have(0).errors
|
174
|
+
|
175
|
+
person.persisted = true
|
176
|
+
person.first_name = nil
|
177
|
+
person.group_valid?(:name)
|
178
|
+
person.should have(0).errors
|
70
179
|
end
|
71
180
|
|
72
|
-
validates_presence_of :sex
|
73
181
|
end
|
182
|
+
end
|
74
183
|
|
75
|
-
|
76
|
-
|
77
|
-
|
184
|
+
describe "#valid?" do
|
185
|
+
it "should run all validation including groups when valid? method called" do
|
186
|
+
Person.class_eval do
|
187
|
+
validation_group :first_name_group do
|
188
|
+
validates_presence_of :first_name
|
189
|
+
end
|
190
|
+
validation_group :last_name_group do
|
191
|
+
validates_presence_of :last_name
|
192
|
+
end
|
193
|
+
validates_presence_of :sex
|
194
|
+
end
|
195
|
+
|
196
|
+
person.valid?
|
197
|
+
person.should have(3).errors
|
198
|
+
end
|
78
199
|
end
|
79
200
|
|
80
|
-
|
81
|
-
|
82
|
-
|
201
|
+
describe "#grouped_errors" do
|
202
|
+
before do
|
203
|
+
Person.class_eval do
|
204
|
+
validation_group :first_name_group do
|
205
|
+
validates_presence_of :first_name
|
206
|
+
end
|
207
|
+
validation_group :last_name_group do
|
208
|
+
validates_presence_of :last_name
|
209
|
+
end
|
210
|
+
validates_presence_of :sex
|
211
|
+
end
|
83
212
|
end
|
84
213
|
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
p.should have(0).errors
|
91
|
-
|
92
|
-
p.save.should be_true
|
93
|
-
p.first_name = nil
|
94
|
-
p.group_valid?(:name)
|
95
|
-
p.should have(0).errors
|
96
|
-
end
|
214
|
+
it 'should return hash of error hashes with validation groups as keys' do
|
215
|
+
errors = person.grouped_errors
|
216
|
+
errors[:first_name_group].should == {:first_name => ["can't be blank"]}
|
217
|
+
errors[:last_name_group].should == {:last_name => ["can't be blank"]}
|
218
|
+
end
|
97
219
|
|
98
|
-
|
99
|
-
|
100
|
-
|
220
|
+
it 'should return hash of errors for validations outside a validation group, for nil key' do
|
221
|
+
errors = person.grouped_errors
|
222
|
+
errors[nil][:sex].should == ["can't be blank"]
|
101
223
|
end
|
102
224
|
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
p.save.should be_true
|
109
|
-
p.group_valid?(:name)
|
110
|
-
p.should have(1).errors
|
111
|
-
p.last_name = 'Smith'
|
112
|
-
p.group_valid?(:name)
|
113
|
-
p.should have(0).errors
|
114
|
-
end
|
225
|
+
it 'should be empty if no errors' do
|
226
|
+
person.first_name = 'Dave'
|
227
|
+
person.last_name = 'Smith'
|
228
|
+
person.sex = 'Male'
|
115
229
|
|
116
|
-
|
117
|
-
Person.class_eval do
|
118
|
-
validation_group :name do
|
119
|
-
validates_presence_of :first_name
|
120
|
-
end
|
121
|
-
validation_group :name do
|
122
|
-
validates_presence_of :last_name
|
123
|
-
end
|
230
|
+
person.grouped_errors.should be_empty
|
124
231
|
end
|
125
232
|
|
126
|
-
p = Person.new
|
127
|
-
p.group_valid?(:name)
|
128
|
-
p.should have(2).errors
|
129
233
|
end
|
130
234
|
|
235
|
+
# Can no longer be done. Unless I find a work around.
|
236
|
+
# it "should allow a validation group to appended with subsequent blocks" do
|
237
|
+
# Person.class_eval do
|
238
|
+
# validation_group :name do
|
239
|
+
# validates_presence_of :first_name
|
240
|
+
# end
|
241
|
+
# validation_group :name do
|
242
|
+
# validates_presence_of :last_name
|
243
|
+
# end
|
244
|
+
# end
|
245
|
+
|
246
|
+
#
|
247
|
+
# person.group_valid?(:name)
|
248
|
+
# puts person.errors.inspect
|
249
|
+
# person.should have(2).errors
|
250
|
+
# end
|
251
|
+
|
131
252
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,36 +1,32 @@
|
|
1
|
-
|
2
|
-
$:.unshift File.expand_path(File.dirname(__FILE__) + '/spec')
|
1
|
+
require 'rspec'
|
3
2
|
|
4
|
-
require '
|
5
|
-
require '
|
6
|
-
require 'active_support'
|
3
|
+
require 'active_support/all'
|
4
|
+
require 'active_model'
|
7
5
|
|
8
6
|
require 'grouped_validations'
|
9
7
|
|
10
|
-
|
11
|
-
|
8
|
+
class TestModel
|
9
|
+
include ActiveSupport::Callbacks
|
10
|
+
include ActiveModel::Validations
|
12
11
|
|
13
|
-
|
14
|
-
|
15
|
-
t.string :first_name
|
16
|
-
t.string :last_name
|
17
|
-
t.integer :sex
|
18
|
-
end
|
12
|
+
attr_accessor :persisted, :first_name, :last_name, :sex
|
13
|
+
alias_method :persisted?, :persisted
|
19
14
|
end
|
20
15
|
|
21
|
-
class Person <
|
16
|
+
class Person < TestModel
|
22
17
|
end
|
23
18
|
|
24
19
|
module SpecHelper
|
25
20
|
def reset_class(klass, &block)
|
21
|
+
superklass = klass.superclass
|
26
22
|
name = klass.name.to_sym
|
27
23
|
Object.send(:remove_const, name)
|
28
|
-
Object.const_set(name, Class.new(
|
24
|
+
Object.const_set(name, Class.new(superklass))
|
29
25
|
new_klass = Object.const_get(name)
|
30
26
|
new_klass.class_eval &block if block_given?
|
31
27
|
end
|
32
28
|
end
|
33
29
|
|
34
|
-
|
30
|
+
RSpec.configure do |config|
|
35
31
|
config.include SpecHelper
|
36
32
|
end
|
metadata
CHANGED
@@ -2,12 +2,12 @@
|
|
2
2
|
name: grouped_validations
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
hash: 19
|
5
|
-
prerelease:
|
5
|
+
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
-
|
10
|
-
version: 0.
|
8
|
+
- 3
|
9
|
+
- 0
|
10
|
+
version: 0.3.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Adam Meehan
|
@@ -15,11 +15,11 @@ autorequire: grouped_validations
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date:
|
18
|
+
date: 2011-03-29 00:00:00 +11:00
|
19
19
|
default_executable:
|
20
20
|
dependencies: []
|
21
21
|
|
22
|
-
description: Define validation groups in
|
22
|
+
description: Define validation groups in a model for greater control over which validations are run.
|
23
23
|
email: adam.meehan@gmail.com
|
24
24
|
executables: []
|
25
25
|
|
@@ -28,13 +28,16 @@ extensions: []
|
|
28
28
|
extra_rdoc_files:
|
29
29
|
- README.rdoc
|
30
30
|
files:
|
31
|
+
- Gemfile
|
32
|
+
- Gemfile.lock
|
31
33
|
- MIT-LICENSE
|
32
34
|
- README.rdoc
|
33
35
|
- Rakefile
|
36
|
+
- grouped_validations.gemspec
|
37
|
+
- init.rb
|
38
|
+
- lib/grouped_validations.rb
|
34
39
|
- lib/grouped_validations/active_model.rb
|
35
|
-
- lib/grouped_validations/active_record.rb
|
36
40
|
- lib/grouped_validations/version.rb
|
37
|
-
- lib/grouped_validations.rb
|
38
41
|
- spec/grouped_validations_spec.rb
|
39
42
|
- spec/spec_helper.rb
|
40
43
|
has_rdoc: true
|
@@ -67,9 +70,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
67
70
|
requirements: []
|
68
71
|
|
69
72
|
rubyforge_project: grouped_validations
|
70
|
-
rubygems_version: 1.
|
73
|
+
rubygems_version: 1.5.2
|
71
74
|
signing_key:
|
72
75
|
specification_version: 3
|
73
|
-
summary: Define validation groups in
|
74
|
-
test_files:
|
75
|
-
|
76
|
+
summary: Define validation groups in a model for greater control over which validations are run.
|
77
|
+
test_files:
|
78
|
+
- spec/grouped_validations_spec.rb
|
79
|
+
- spec/spec_helper.rb
|
@@ -1,47 +0,0 @@
|
|
1
|
-
module GroupedValidations
|
2
|
-
|
3
|
-
module ClassMethods
|
4
|
-
|
5
|
-
def define_group_validation_callbacks(group)
|
6
|
-
base_name = :"validate_#{group}"
|
7
|
-
define_callbacks base_name, :"#{base_name}_on_create", :"#{base_name}_on_update"
|
8
|
-
end
|
9
|
-
|
10
|
-
def validation_method_with_groups(on)
|
11
|
-
if @current_validation_group
|
12
|
-
base_name = :"validate_#{@current_validation_group}"
|
13
|
-
case on
|
14
|
-
when :save then base_name
|
15
|
-
when :create then :"#{base_name}_on_create"
|
16
|
-
when :update then :"#{base_name}_on_update"
|
17
|
-
end
|
18
|
-
else
|
19
|
-
validation_method_without_groups on
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
end
|
24
|
-
|
25
|
-
module InstanceMethods
|
26
|
-
|
27
|
-
def valid_with_groups?
|
28
|
-
valid_without_groups?
|
29
|
-
(validation_groups || []).each do |group|
|
30
|
-
run_group_validation_callbacks group
|
31
|
-
end
|
32
|
-
errors.empty?
|
33
|
-
end
|
34
|
-
|
35
|
-
def run_group_validation_callbacks(group)
|
36
|
-
base_name = :"validate_#{group}"
|
37
|
-
run_callbacks(base_name)
|
38
|
-
if new_record?
|
39
|
-
run_callbacks(:"#{base_name}_on_create")
|
40
|
-
else
|
41
|
-
run_callbacks(:"#{base_name}_on_update")
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
end
|
46
|
-
|
47
|
-
end
|