assistance 0.1.1 → 0.1.2
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/CHANGELOG +4 -0
- data/Rakefile +1 -1
- data/lib/assistance.rb +1 -0
- data/lib/assistance/validation.rb +239 -0
- data/spec/validation_spec.rb +291 -0
- metadata +4 -2
data/CHANGELOG
CHANGED
data/Rakefile
CHANGED
@@ -9,7 +9,7 @@ include FileUtils
|
|
9
9
|
# Configuration
|
10
10
|
##############################################################################
|
11
11
|
NAME = "assistance"
|
12
|
-
VERS = "0.1.
|
12
|
+
VERS = "0.1.2"
|
13
13
|
CLEAN.include ["**/.*.sw?", "pkg/*", ".config", "doc/*", "coverage/*"]
|
14
14
|
RDOC_OPTS = [
|
15
15
|
"--quiet",
|
data/lib/assistance.rb
CHANGED
@@ -0,0 +1,239 @@
|
|
1
|
+
# The Validations module provides validation capabilities as a mixin. When
|
2
|
+
# included into a class, it enhances the class with class and instance
|
3
|
+
# methods for defining validations and validating class instances.
|
4
|
+
#
|
5
|
+
# The Validation emulates the validation capabilities of ActiveRecord, and
|
6
|
+
# provides methods for validating acceptance, confirmation, presence, format,
|
7
|
+
# length and numericality of attributes.
|
8
|
+
#
|
9
|
+
# To use validations, you need to include the Validation module in your
|
10
|
+
# class:
|
11
|
+
#
|
12
|
+
# class MyClass
|
13
|
+
# include Validation
|
14
|
+
# validates_length_of :password, :minimum => 6
|
15
|
+
# end
|
16
|
+
module Validation
|
17
|
+
# Includes the Validation class methods into the including class.
|
18
|
+
def self.included(c)
|
19
|
+
c.extend ClassMethods
|
20
|
+
end
|
21
|
+
|
22
|
+
# Returns the validation errors associated with the object.
|
23
|
+
def errors
|
24
|
+
@errors ||= Errors.new
|
25
|
+
end
|
26
|
+
|
27
|
+
# Validates the object.
|
28
|
+
def validate
|
29
|
+
errors.clear
|
30
|
+
self.class.validate(self)
|
31
|
+
end
|
32
|
+
|
33
|
+
# Validates the object and returns true if no errors are reported.
|
34
|
+
def valid?
|
35
|
+
validate
|
36
|
+
errors.empty?
|
37
|
+
end
|
38
|
+
|
39
|
+
# Validation::Errors represents validation errors.
|
40
|
+
class Errors
|
41
|
+
# Initializes a new instance of validation errors.
|
42
|
+
def initialize
|
43
|
+
@errors = Hash.new {|h, k| h[k] = []}
|
44
|
+
end
|
45
|
+
|
46
|
+
# Returns true if no errors are stored.
|
47
|
+
def empty?
|
48
|
+
@errors.empty?
|
49
|
+
end
|
50
|
+
|
51
|
+
# Clears all errors.
|
52
|
+
def clear
|
53
|
+
@errors.clear
|
54
|
+
end
|
55
|
+
|
56
|
+
# Returns the errors for the given attribute.
|
57
|
+
def on(att)
|
58
|
+
@errors[att]
|
59
|
+
end
|
60
|
+
alias_method :[], :on
|
61
|
+
|
62
|
+
# Adds an error for the given attribute.
|
63
|
+
def add(att, msg)
|
64
|
+
@errors[att] << msg
|
65
|
+
end
|
66
|
+
|
67
|
+
# Returns an array of fully-formatted error messages.
|
68
|
+
def full_messages
|
69
|
+
@errors.inject([]) do |m, kv| att, errors = *kv
|
70
|
+
errors.each {|e| m << "#{att} #{e}"}
|
71
|
+
m
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
# The Generator class is used to generate validation definitions using
|
77
|
+
# the validates {} idiom.
|
78
|
+
class Generator
|
79
|
+
# Initializes a new generator.
|
80
|
+
def initialize(receiver ,&block)
|
81
|
+
@receiver = receiver
|
82
|
+
instance_eval(&block)
|
83
|
+
end
|
84
|
+
|
85
|
+
# Delegates method calls to the receiver by calling receiver.validates_xxx.
|
86
|
+
def method_missing(m, *args)
|
87
|
+
@receiver.send(:"validates_#{m}", *args)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
# Validation class methods.
|
92
|
+
module ClassMethods
|
93
|
+
# Defines validations by converting a longhand block into a series of
|
94
|
+
# shorthand definitions. For example:
|
95
|
+
#
|
96
|
+
# class MyClass
|
97
|
+
# include Validation
|
98
|
+
# validates do
|
99
|
+
# length_of :name, :minimum => 6
|
100
|
+
# length_of :password, :minimum => 8
|
101
|
+
# end
|
102
|
+
# end
|
103
|
+
#
|
104
|
+
# is equivalent to:
|
105
|
+
# class MyClass
|
106
|
+
# include Validation
|
107
|
+
# validates_length_of :name, :minimum => 6
|
108
|
+
# validates_length_of :password, :minimum => 8
|
109
|
+
# end
|
110
|
+
def validates(&block)
|
111
|
+
Generator.new(self, &block)
|
112
|
+
end
|
113
|
+
|
114
|
+
# Returns the validations hash for the class.
|
115
|
+
def validations
|
116
|
+
@validations ||= Hash.new {|h, k| h[k] = []}
|
117
|
+
end
|
118
|
+
|
119
|
+
# Returns true if validations are defined.
|
120
|
+
def has_validations?
|
121
|
+
!validations.empty?
|
122
|
+
end
|
123
|
+
|
124
|
+
# Validates the given instance.
|
125
|
+
def validate(o)
|
126
|
+
validations.each do |att, procs|
|
127
|
+
v = o.send(att)
|
128
|
+
procs.each {|p| p[o, att, v]}
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
# Adds a validation for each of the given attributes using the supplied
|
133
|
+
# block. The block must accept three arguments: instance, attribute and
|
134
|
+
# value, e.g.:
|
135
|
+
#
|
136
|
+
# validates_each :name, :password do |object, attribute, value|
|
137
|
+
# object.errors[attribute] << 'is not nice' unless value.nice?
|
138
|
+
# end
|
139
|
+
def validates_each(*atts, &block)
|
140
|
+
atts.each {|a| validations[a] << block}
|
141
|
+
end
|
142
|
+
|
143
|
+
# Validates acceptance of an attribute.
|
144
|
+
def validates_acceptance_of(*atts)
|
145
|
+
opts = {
|
146
|
+
:message => 'is not accepted',
|
147
|
+
:allow_nil => true,
|
148
|
+
:accept => '1'
|
149
|
+
}.merge!(atts.extract_options!)
|
150
|
+
|
151
|
+
validates_each(*atts) do |o, a, v|
|
152
|
+
next if (v.nil? && opts[:allow_nil]) || (v.blank? && opts[:allow_blank])
|
153
|
+
o.errors[a] << opts[:message] unless v == opts[:accept]
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
# Validates confirmation of an attribute.
|
158
|
+
def validates_confirmation_of(*atts)
|
159
|
+
opts = {
|
160
|
+
:message => 'is not confirmed',
|
161
|
+
}.merge!(atts.extract_options!)
|
162
|
+
|
163
|
+
validates_each(*atts) do |o, a, v|
|
164
|
+
next if (v.nil? && opts[:allow_nil]) || (v.blank? && opts[:allow_blank])
|
165
|
+
c = o.send(:"#{a}_confirmation")
|
166
|
+
o.errors[a] << opts[:message] unless v == c
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
# Validates the format of an attribute.
|
171
|
+
def validates_format_of(*atts)
|
172
|
+
opts = {
|
173
|
+
:message => 'is invalid',
|
174
|
+
}.merge!(atts.extract_options!)
|
175
|
+
|
176
|
+
unless opts[:with].is_a?(Regexp)
|
177
|
+
raise ArgumentError, "A regular expression must be supplied as the :with option of the options hash"
|
178
|
+
end
|
179
|
+
|
180
|
+
validates_each(*atts) do |o, a, v|
|
181
|
+
next if (v.nil? && opts[:allow_nil]) || (v.blank? && opts[:allow_blank])
|
182
|
+
o.errors[a] << opts[:message] unless v.to_s =~ opts[:with]
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
# Validates the length of an attribute.
|
187
|
+
def validates_length_of(*atts)
|
188
|
+
opts = {
|
189
|
+
:too_long => 'is too long',
|
190
|
+
:too_short => 'is too short',
|
191
|
+
:wrong_length => 'is the wrong length'
|
192
|
+
}.merge!(atts.extract_options!)
|
193
|
+
|
194
|
+
validates_each(*atts) do |o, a, v|
|
195
|
+
next if (v.nil? && opts[:allow_nil]) || (v.blank? && opts[:allow_blank])
|
196
|
+
if m = opts[:maximum]
|
197
|
+
o.errors[a] << (opts[:message] || opts[:too_long]) unless v && v.size <= m
|
198
|
+
end
|
199
|
+
if m = opts[:minimum]
|
200
|
+
o.errors[a] << (opts[:message] || opts[:too_short]) unless v && v.size >= m
|
201
|
+
end
|
202
|
+
if i = opts[:is]
|
203
|
+
o.errors[a] << (opts[:message] || opts[:wrong_length]) unless v && v.size == i
|
204
|
+
end
|
205
|
+
if w = opts[:within]
|
206
|
+
o.errors[a] << (opts[:message] || opts[:wrong_length]) unless v && w.include?(v.size)
|
207
|
+
end
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
NUMBER_RE = /^\d*\.{0,1}\d+$/
|
212
|
+
INTEGER_RE = /\A[+-]?\d+\Z/
|
213
|
+
|
214
|
+
# Validates whether an attribute is a number.
|
215
|
+
def validates_numericality_of(*atts)
|
216
|
+
opts = {
|
217
|
+
:message => 'is not a number',
|
218
|
+
}.merge!(atts.extract_options!)
|
219
|
+
|
220
|
+
re = opts[:only_integer] ? INTEGER_RE : NUMBER_RE
|
221
|
+
|
222
|
+
validates_each(*atts) do |o, a, v|
|
223
|
+
next if (v.nil? && opts[:allow_nil]) || (v.blank? && opts[:allow_blank])
|
224
|
+
o.errors[a] << opts[:message] unless v.to_s =~ re
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
# Validates the presence of an attribute.
|
229
|
+
def validates_presence_of(*atts)
|
230
|
+
opts = {
|
231
|
+
:message => 'is not present',
|
232
|
+
}.merge!(atts.extract_options!)
|
233
|
+
|
234
|
+
validates_each(*atts) do |o, a, v|
|
235
|
+
o.errors[a] << opts[:message] unless v && !v.blank?
|
236
|
+
end
|
237
|
+
end
|
238
|
+
end
|
239
|
+
end
|
@@ -0,0 +1,291 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), "spec_helper")
|
2
|
+
|
3
|
+
describe "Validation::Errors" do
|
4
|
+
setup do
|
5
|
+
@errors = Validation::Errors.new
|
6
|
+
class Validation::Errors
|
7
|
+
attr_accessor :errors
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
specify "should be clearable using #clear" do
|
12
|
+
@errors.errors = {1 => 2, 3 => 4}
|
13
|
+
@errors.clear
|
14
|
+
@errors.errors.should == {}
|
15
|
+
end
|
16
|
+
|
17
|
+
specify "should be empty if no errors are added" do
|
18
|
+
@errors.should be_empty
|
19
|
+
@errors[:blah] << "blah"
|
20
|
+
@errors.should_not be_empty
|
21
|
+
end
|
22
|
+
|
23
|
+
specify "should return errors for a specific attribute using #on or #[]" do
|
24
|
+
@errors[:blah].should == []
|
25
|
+
@errors.on(:blah).should == []
|
26
|
+
|
27
|
+
@errors[:blah] << 'blah'
|
28
|
+
@errors[:blah].should == ['blah']
|
29
|
+
@errors.on(:blah).should == ['blah']
|
30
|
+
|
31
|
+
@errors[:bleu].should == []
|
32
|
+
@errors.on(:bleu).should == []
|
33
|
+
end
|
34
|
+
|
35
|
+
specify "should accept errors using #[] << or #add" do
|
36
|
+
@errors[:blah] << 'blah'
|
37
|
+
@errors[:blah].should == ['blah']
|
38
|
+
|
39
|
+
@errors.add :blah, 'zzzz'
|
40
|
+
@errors[:blah].should == ['blah', 'zzzz']
|
41
|
+
end
|
42
|
+
|
43
|
+
specify "should return full messages using #full_messages" do
|
44
|
+
@errors.full_messages.should == []
|
45
|
+
|
46
|
+
@errors[:blow] << 'blieuh'
|
47
|
+
@errors[:blow] << 'blich'
|
48
|
+
@errors[:blay] << 'bliu'
|
49
|
+
msgs = @errors.full_messages
|
50
|
+
msgs.size.should == 3
|
51
|
+
msgs.should include('blow blieuh', 'blow blich', 'blay bliu')
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
describe Validation do
|
56
|
+
setup do
|
57
|
+
@c = Class.new do
|
58
|
+
include Validation
|
59
|
+
|
60
|
+
def self.validates_coolness_of(attr)
|
61
|
+
validates_each(attr) {|o, a, v| o.errors[a] << 'is not cool' if v != :cool}
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
@d = Class.new do
|
66
|
+
attr_accessor :errors
|
67
|
+
def initialize; @errors = Validation::Errors.new; end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
specify "should respond to validates, validations, has_validations?" do
|
72
|
+
@c.should respond_to(:validations)
|
73
|
+
@c.should respond_to(:has_validations?)
|
74
|
+
end
|
75
|
+
|
76
|
+
specify "should acccept validation definitions using validates_each" do
|
77
|
+
@c.validates_each(:xx, :yy) {|o, a, v| o.errors[a] << 'too low' if v < 50}
|
78
|
+
|
79
|
+
@c.validations[:xx].size.should == 1
|
80
|
+
@c.validations[:yy].size.should == 1
|
81
|
+
|
82
|
+
o = @d.new
|
83
|
+
@c.validations[:xx].first.call(o, :aa, 40)
|
84
|
+
@c.validations[:yy].first.call(o, :bb, 60)
|
85
|
+
|
86
|
+
o.errors.full_messages.should == ['aa too low']
|
87
|
+
end
|
88
|
+
|
89
|
+
specify "should return true/false for has_validations?" do
|
90
|
+
@c.has_validations?.should == false
|
91
|
+
@c.validates_each(:xx) {1}
|
92
|
+
@c.has_validations?.should == true
|
93
|
+
end
|
94
|
+
|
95
|
+
specify "should provide a validates method that takes block with validation definitions" do
|
96
|
+
@c.validates do
|
97
|
+
coolness_of :blah
|
98
|
+
end
|
99
|
+
@c.validations[:blah].should_not be_empty
|
100
|
+
|
101
|
+
o = @d.new
|
102
|
+
@c.validations[:blah].first.call(o, :ttt, 40)
|
103
|
+
o.errors.full_messages.should == ['ttt is not cool']
|
104
|
+
o.errors.clear
|
105
|
+
@c.validations[:blah].first.call(o, :ttt, :cool)
|
106
|
+
o.errors.should be_empty
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
describe "A Validation instance" do
|
111
|
+
setup do
|
112
|
+
@c = Class.new do
|
113
|
+
attr_accessor :score
|
114
|
+
|
115
|
+
include Validation
|
116
|
+
|
117
|
+
validates_each :score do |o, a, v|
|
118
|
+
o.errors[a] << 'too low' if v < 87
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
@o = @c.new
|
123
|
+
end
|
124
|
+
|
125
|
+
specify "should supply a #valid? method that returns true if validations pass" do
|
126
|
+
@o.score = 50
|
127
|
+
@o.should_not be_valid
|
128
|
+
@o.score = 100
|
129
|
+
@o.should be_valid
|
130
|
+
end
|
131
|
+
|
132
|
+
specify "should provide an errors object" do
|
133
|
+
@o.score = 100
|
134
|
+
@o.should be_valid
|
135
|
+
@o.errors.should be_empty
|
136
|
+
|
137
|
+
@o.score = 86
|
138
|
+
@o.should_not be_valid
|
139
|
+
@o.errors[:score].should == ['too low']
|
140
|
+
@o.errors[:blah].should be_empty
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
describe Validation::Generator do
|
145
|
+
setup do
|
146
|
+
$testit = nil
|
147
|
+
|
148
|
+
@c = Class.new do
|
149
|
+
include Validation
|
150
|
+
|
151
|
+
def self.validates_blah
|
152
|
+
$testit = 1324
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
specify "should instance_eval the block, sending everything to its receiver" do
|
158
|
+
Validation::Generator.new(@c) do
|
159
|
+
blah
|
160
|
+
end
|
161
|
+
$testit.should == 1324
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
describe "Validations" do
|
166
|
+
setup do
|
167
|
+
@c = Class.new do
|
168
|
+
attr_accessor :value
|
169
|
+
include Validation
|
170
|
+
end
|
171
|
+
@m = @c.new
|
172
|
+
end
|
173
|
+
|
174
|
+
specify "should validate acceptance_of" do
|
175
|
+
@c.validates_acceptance_of :value
|
176
|
+
@m.should be_valid
|
177
|
+
@m.value = '1'
|
178
|
+
@m.should be_valid
|
179
|
+
end
|
180
|
+
|
181
|
+
specify "should validate acceptance_of with accept" do
|
182
|
+
@c.validates_acceptance_of :value, :accept => 'true'
|
183
|
+
@m.value = '1'
|
184
|
+
@m.should_not be_valid
|
185
|
+
@m.value = 'true'
|
186
|
+
@m.should be_valid
|
187
|
+
end
|
188
|
+
|
189
|
+
specify "should validate acceptance_of with allow_nil => false" do
|
190
|
+
@c.validates_acceptance_of :value, :allow_nil => false
|
191
|
+
@m.should_not be_valid
|
192
|
+
end
|
193
|
+
|
194
|
+
specify "should validate confirmation_of" do
|
195
|
+
@c.send(:attr_accessor, :value_confirmation)
|
196
|
+
@c.validates_confirmation_of :value
|
197
|
+
|
198
|
+
@m.value = 'blah'
|
199
|
+
@m.should_not be_valid
|
200
|
+
|
201
|
+
@m.value_confirmation = 'blah'
|
202
|
+
@m.should be_valid
|
203
|
+
end
|
204
|
+
|
205
|
+
specify "should validate format_of" do
|
206
|
+
@c.validates_format_of :value, :with => /.+_.+/
|
207
|
+
@m.value = 'abc_'
|
208
|
+
@m.should_not be_valid
|
209
|
+
@m.value = 'abc_def'
|
210
|
+
@m.should be_valid
|
211
|
+
end
|
212
|
+
|
213
|
+
specify "should raise for validate_format_of without regexp" do
|
214
|
+
proc {@c.validates_format_of :value}.should raise_error(ArgumentError)
|
215
|
+
proc {@c.validates_format_of :value, :with => :blah}.should raise_error(ArgumentError)
|
216
|
+
end
|
217
|
+
|
218
|
+
specify "should validate length_of with maximum" do
|
219
|
+
@c.validates_length_of :value, :maximum => 5
|
220
|
+
@m.should_not be_valid
|
221
|
+
@m.value = '12345'
|
222
|
+
@m.should be_valid
|
223
|
+
@m.value = '123456'
|
224
|
+
@m.should_not be_valid
|
225
|
+
end
|
226
|
+
|
227
|
+
specify "should validate length_of with minimum" do
|
228
|
+
@c.validates_length_of :value, :minimum => 5
|
229
|
+
@m.should_not be_valid
|
230
|
+
@m.value = '12345'
|
231
|
+
@m.should be_valid
|
232
|
+
@m.value = '1234'
|
233
|
+
@m.should_not be_valid
|
234
|
+
end
|
235
|
+
|
236
|
+
specify "should validate length_of with within" do
|
237
|
+
@c.validates_length_of :value, :within => 2..5
|
238
|
+
@m.should_not be_valid
|
239
|
+
@m.value = '12345'
|
240
|
+
@m.should be_valid
|
241
|
+
@m.value = '1'
|
242
|
+
@m.should_not be_valid
|
243
|
+
@m.value = '123456'
|
244
|
+
@m.should_not be_valid
|
245
|
+
end
|
246
|
+
|
247
|
+
specify "should validate length_of with is" do
|
248
|
+
@c.validates_length_of :value, :is => 3
|
249
|
+
@m.should_not be_valid
|
250
|
+
@m.value = '123'
|
251
|
+
@m.should be_valid
|
252
|
+
@m.value = '12'
|
253
|
+
@m.should_not be_valid
|
254
|
+
@m.value = '1234'
|
255
|
+
@m.should_not be_valid
|
256
|
+
end
|
257
|
+
|
258
|
+
specify "should validate length_of with allow_nil" do
|
259
|
+
@c.validates_length_of :value, :is => 3, :allow_nil => true
|
260
|
+
@m.should be_valid
|
261
|
+
end
|
262
|
+
|
263
|
+
specify "should validate numericality_of" do
|
264
|
+
@c.validates_numericality_of :value
|
265
|
+
@m.value = 'blah'
|
266
|
+
@m.should_not be_valid
|
267
|
+
@m.value = '123'
|
268
|
+
@m.should be_valid
|
269
|
+
@m.value = '123.1231'
|
270
|
+
@m.should be_valid
|
271
|
+
end
|
272
|
+
|
273
|
+
specify "should validate numericality_of with only_integer" do
|
274
|
+
@c.validates_numericality_of :value, :only_integer => true
|
275
|
+
@m.value = 'blah'
|
276
|
+
@m.should_not be_valid
|
277
|
+
@m.value = '123'
|
278
|
+
@m.should be_valid
|
279
|
+
@m.value = '123.1231'
|
280
|
+
@m.should_not be_valid
|
281
|
+
end
|
282
|
+
|
283
|
+
specify "should validate presence_of" do
|
284
|
+
@c.validates_presence_of :value
|
285
|
+
@m.should_not be_valid
|
286
|
+
@m.value = ''
|
287
|
+
@m.should_not be_valid
|
288
|
+
@m.value = 1234
|
289
|
+
@m.should be_valid
|
290
|
+
end
|
291
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: assistance
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ezra Zygmuntowicz, Sam Smoot, Sharon Rosner
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2008-01-
|
12
|
+
date: 2008-01-21 00:00:00 +02:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|
@@ -36,6 +36,7 @@ files:
|
|
36
36
|
- spec/spec.opts
|
37
37
|
- spec/spec_helper.rb
|
38
38
|
- spec/time_calculations_spec.rb
|
39
|
+
- spec/validation_spec.rb
|
39
40
|
- lib/assistance
|
40
41
|
- lib/assistance/blank.rb
|
41
42
|
- lib/assistance/connection_pool.rb
|
@@ -44,6 +45,7 @@ files:
|
|
44
45
|
- lib/assistance/inflections.rb
|
45
46
|
- lib/assistance/inflector.rb
|
46
47
|
- lib/assistance/time_calculations.rb
|
48
|
+
- lib/assistance/validation.rb
|
47
49
|
- lib/assistance.rb
|
48
50
|
- CHANGELOG
|
49
51
|
has_rdoc: true
|