validates_type 1.1.0 → 1.2.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.
- checksums.yaml +4 -4
- data/.gitignore +2 -0
- data/README.md +4 -1
- data/lib/validates_type.rb +26 -8
- data/spec/active_model/types_spec.rb +31 -0
- data/spec/active_model_helper.rb +3 -3
- data/spec/active_record_helper.rb +1 -1
- data/spec/activerecord/types_spec.rb +45 -0
- data/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4eaad53649c687b0db1d873919a5e0d3977abfc1
|
4
|
+
data.tar.gz: 216e38fc24aed68917f29979875fc0518bbaa5f2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0d3d79da0e73d4a8a37abb36ea65c5e936e862a655faf280a95233d50f5f61759c6214cd8d935214b62fe4ab334cc548ba5db878a47381c73a8a12f477f002e0
|
7
|
+
data.tar.gz: 517ec6573c60bfe54372fec7c9f9681ec9735b63eb5955ad6df79510d7fbdceba22a96a21a0e781a64a031cc5f3f6efeaa43a47d01eb2bbb2345d7a8073115dc
|
data/.gitignore
CHANGED
data/README.md
CHANGED
@@ -37,6 +37,9 @@ class Foo < ActiveRecord::Base
|
|
37
37
|
|
38
38
|
# validate that attribute :birthday is a Date or blank
|
39
39
|
validates_type :birthday, :date, allow_blank: true
|
40
|
+
|
41
|
+
# validate that attribute :fox is of type Custom
|
42
|
+
validates_type :fox, Custom
|
40
43
|
end
|
41
44
|
```
|
42
45
|
|
@@ -98,4 +101,4 @@ end
|
|
98
101
|
- `:symbol`
|
99
102
|
- `:time`
|
100
103
|
|
101
|
-
|
104
|
+
#### Any class name, possibly something custom defined in your app, is also game.
|
data/lib/validates_type.rb
CHANGED
@@ -16,7 +16,7 @@ module ActiveModel
|
|
16
16
|
# return: result of ActiveModel::Validations::EachValidator initialize
|
17
17
|
def initialize(options)
|
18
18
|
merged_options = {
|
19
|
-
:message => "is expected to be a #{
|
19
|
+
:message => "is expected to be a #{ type_class(options[:type]) } and is not."
|
20
20
|
}.merge(options)
|
21
21
|
|
22
22
|
super(merged_options)
|
@@ -31,7 +31,7 @@ module ActiveModel
|
|
31
31
|
# return: nil
|
32
32
|
def validate_each(record, attribute, value)
|
33
33
|
value_to_test = type_before_coercion(record, attribute, value)
|
34
|
-
expected_type =
|
34
|
+
expected_type = type_class(options[:type])
|
35
35
|
|
36
36
|
add_errors_or_raise(options, record, attribute) unless value_to_test.is_a?(expected_type)
|
37
37
|
end
|
@@ -71,6 +71,21 @@ module ActiveModel
|
|
71
71
|
end
|
72
72
|
end
|
73
73
|
|
74
|
+
# Helper method to get back a class constant from the given type option
|
75
|
+
# If the type option is a class, it will be returned as is.
|
76
|
+
# If it is not a class, the method will try to convert it to a class constant.
|
77
|
+
#
|
78
|
+
# ex:
|
79
|
+
# type_class(:string) -> String
|
80
|
+
# type_class(String) -> String
|
81
|
+
# type_class(Custom) -> Custom
|
82
|
+
# @type_class
|
83
|
+
# param: type <Class, Symbol>
|
84
|
+
# return: <Class> class constant
|
85
|
+
def type_class(type)
|
86
|
+
@type_class ||= type.is_a?(Class) ? type : symbol_class(type)
|
87
|
+
end
|
88
|
+
|
74
89
|
# Helper method to convert a symbol into a class constant
|
75
90
|
#
|
76
91
|
# ex:
|
@@ -79,10 +94,10 @@ module ActiveModel
|
|
79
94
|
# symbol_class(:hash) -> Hash
|
80
95
|
#
|
81
96
|
# @symbol_class
|
82
|
-
# param: symbol <Symbol> - symbol to turn into a
|
97
|
+
# param: symbol <Symbol> - symbol to turn into a class constant
|
83
98
|
# return: class constant of supported types or raises UnsupportedType
|
84
99
|
def symbol_class(symbol)
|
85
|
-
|
100
|
+
{
|
86
101
|
:array => Array,
|
87
102
|
:boolean => Boolean,
|
88
103
|
:float => Float,
|
@@ -122,20 +137,23 @@ module ActiveModel
|
|
122
137
|
# - :date
|
123
138
|
# - :big_decimal
|
124
139
|
#
|
140
|
+
# Also validates the type of an attribute given a custom type class constant.
|
141
|
+
#
|
125
142
|
# class Foo
|
126
143
|
# include ActiveModel::Validations
|
127
144
|
#
|
128
|
-
# attr_accessor :thing, :something
|
145
|
+
# attr_accessor :thing, :something, :custom_thing
|
129
146
|
#
|
130
147
|
# validates_type :thing, :boolean
|
131
148
|
# validates_type :something, :array
|
149
|
+
# validates_type :custom_thing, Custom
|
132
150
|
# end
|
133
151
|
#
|
134
152
|
# @validates_type
|
135
153
|
# param: attribute_name <Symbol> - name of attribute to validate
|
136
|
-
# param: attribute_type <Symbol> - type of attribute to validate against
|
137
|
-
# param: options <Hash>
|
138
|
-
#
|
154
|
+
# param: attribute_type <Symbol, Class> - type of attribute to validate against
|
155
|
+
# param: options <Hash> - other common options to validate methods calls
|
156
|
+
# i.e. message: 'my custom error message'
|
139
157
|
# return: nil
|
140
158
|
def validates_type(attribute_name, attribute_type, options = {})
|
141
159
|
args = ValidatesType::Arguments.new(attribute_name, attribute_type, options)
|
@@ -292,4 +292,35 @@ describe 'ValidatesType' do
|
|
292
292
|
end
|
293
293
|
end
|
294
294
|
end
|
295
|
+
|
296
|
+
context 'custom class' do
|
297
|
+
class Custom; end
|
298
|
+
subject { ActiveModel::TypeValidationTestClass.set_accessor_and_long_validator(Custom) }
|
299
|
+
|
300
|
+
before do
|
301
|
+
subject.attribute = value
|
302
|
+
end
|
303
|
+
|
304
|
+
context 'field value is of type Custom' do
|
305
|
+
let(:value) { Custom.new }
|
306
|
+
|
307
|
+
specify do
|
308
|
+
expect(subject).to be_valid
|
309
|
+
end
|
310
|
+
end
|
311
|
+
|
312
|
+
context 'field value is not of type Custom' do
|
313
|
+
let(:value) { -1 }
|
314
|
+
|
315
|
+
specify do
|
316
|
+
expect(subject).to_not be_valid
|
317
|
+
end
|
318
|
+
|
319
|
+
specify do
|
320
|
+
subject.validate
|
321
|
+
expect(subject.errors).to_not be_empty
|
322
|
+
expect(subject.errors.messages[:attribute][0]).to match(/is expected to be a Custom and is not/)
|
323
|
+
end
|
324
|
+
end
|
325
|
+
end
|
295
326
|
end
|
data/spec/active_model_helper.rb
CHANGED
@@ -12,14 +12,14 @@ module ActiveModel
|
|
12
12
|
# end
|
13
13
|
#
|
14
14
|
# @set_accessor_and_long_validator
|
15
|
-
# param: type <Symbol> - type which to validate against
|
15
|
+
# param: type <Symbol, Class> - type which to validate against
|
16
16
|
# param: options<Hash *Optional*> - extra modifiers/custom messaging
|
17
17
|
# return: TypeValidationTestClass instance with set validator
|
18
18
|
def self.set_accessor_and_long_validator(type, options = {})
|
19
19
|
self.new.tap do |test_class|
|
20
20
|
test_class._validators = {}
|
21
21
|
test_class.class_eval { attr_accessor :attribute }
|
22
|
-
test_class.class_eval { validates_type :attribute, type
|
22
|
+
test_class.class_eval { validates_type :attribute, type, options }
|
23
23
|
end
|
24
24
|
end
|
25
25
|
|
@@ -33,7 +33,7 @@ module ActiveModel
|
|
33
33
|
# end
|
34
34
|
#
|
35
35
|
# @set_accessor_and_long_validator
|
36
|
-
# param: type <Symbol> - type which to validate against
|
36
|
+
# param: type <Symbol, Class> - type which to validate against
|
37
37
|
# param: options<Hash *Optional*> - extra modifiers/custom messaging
|
38
38
|
# return: TypeValidationTestClass instance with set validator
|
39
39
|
def self.set_accessor_and_validator(type, options = {})
|
@@ -20,7 +20,7 @@ class TypeValidationTest < ActiveRecord::Base
|
|
20
20
|
def self.set_accessor_and_long_validator(type, options = {})
|
21
21
|
self.new.tap do |test_class|
|
22
22
|
test_class._validators = {}
|
23
|
-
test_class.class_eval { validates_type :test_attribute, type
|
23
|
+
test_class.class_eval { validates_type :test_attribute, type, options }
|
24
24
|
end
|
25
25
|
end
|
26
26
|
|
@@ -385,4 +385,49 @@ describe 'ValidatesType' do
|
|
385
385
|
end
|
386
386
|
end
|
387
387
|
end
|
388
|
+
|
389
|
+
context 'custom class' do
|
390
|
+
drop_and_create_column_with_type(:string)
|
391
|
+
class Custom; end
|
392
|
+
subject { TypeValidationTest.set_accessor_and_long_validator(Custom) }
|
393
|
+
|
394
|
+
before do
|
395
|
+
subject.test_attribute = value
|
396
|
+
end
|
397
|
+
|
398
|
+
context 'field value is of type Custom' do
|
399
|
+
let(:value) { Custom.new }
|
400
|
+
|
401
|
+
specify do
|
402
|
+
expect(subject).to be_valid
|
403
|
+
end
|
404
|
+
end
|
405
|
+
|
406
|
+
context 'field value is not of type Custom' do
|
407
|
+
let(:value) { -1 }
|
408
|
+
|
409
|
+
specify do
|
410
|
+
expect(subject).to_not be_valid
|
411
|
+
end
|
412
|
+
|
413
|
+
specify do
|
414
|
+
subject.validate
|
415
|
+
expect(subject.errors).to_not be_empty
|
416
|
+
expect(subject.errors.messages[:test_attribute][0]).to match(/is expected to be a Custom and is not/)
|
417
|
+
end
|
418
|
+
end
|
419
|
+
|
420
|
+
context 'passing in a custom message' do
|
421
|
+
subject { TypeValidationTest.set_accessor_and_long_validator(Custom, message: 'is not Custom!') }
|
422
|
+
|
423
|
+
context 'when validation fails' do
|
424
|
+
let(:value) { 1 }
|
425
|
+
|
426
|
+
specify do
|
427
|
+
subject.validate
|
428
|
+
expect(subject.errors.messages[:test_attribute][0]).to match(/is not Custom!/)
|
429
|
+
end
|
430
|
+
end
|
431
|
+
end
|
432
|
+
end
|
388
433
|
end
|
data/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: validates_type
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jake Yesbeck
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-10-
|
11
|
+
date: 2015-10-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: ruby-boolean
|