validated_object 1.1.0 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.travis.yml +1 -1
- data/README.md +90 -35
- data/lib/validated_object/version.rb +2 -1
- data/lib/validated_object.rb +15 -12
- data/script/demo.rb +17 -0
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: ba509cb442a5ef4c67d7186bd58b329551c00e137ec2c2b1cd7c4e268b92344a
|
4
|
+
data.tar.gz: 79a4f93be0f9919bf189f01258ed0379382df90aa01bc69a5ae883d924d53527
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d626a9f7e53258a92e5a0fa3a8cfabf4c7ba38e2c960466e29aaf98dacb7e433c02e3facaca3d2c96a3bd769077a3c3d6e1378b9631a48b6e307db88c8b91f98
|
7
|
+
data.tar.gz: 73771320ac4176387bbe336057c2459b5772898a68b380518e149f93af8a29243312462adda6f498a15fb777cb8e803e0db684bc41c130fc316135b63dcc9dac
|
data/.travis.yml
CHANGED
data/README.md
CHANGED
@@ -2,78 +2,133 @@
|
|
2
2
|
|
3
3
|
# ValidatedObject
|
4
4
|
|
5
|
-
|
6
|
-
[ActiveModel::Validations](http://api.rubyonrails.org/classes/ActiveModel/Validations/ClassMethods.html#method-i-validates)
|
7
|
-
to create self-validating Plain Old Ruby objects. I wrote it for helping with CSV data imports into my Rails apps.
|
8
|
-
Very readable error messages are also important in that context, to track down parsing errors. This gem provides those too.
|
5
|
+
Plain Old Ruby Objects + Rails Validations = self-checking Ruby objects.
|
9
6
|
|
10
7
|
|
11
|
-
##
|
8
|
+
## Goals
|
12
9
|
|
13
|
-
|
10
|
+
* Very readable error messages
|
11
|
+
* Clean, minimal syntax
|
14
12
|
|
15
|
-
|
16
|
-
|
17
|
-
```
|
13
|
+
This is a small layer around
|
14
|
+
[ActiveModel::Validations](http://api.rubyonrails.org/classes/ActiveModel/Validations/ClassMethods.html#method-i-validates). (About 18 lines of code.) So if you know how to use Rails Validations, you're good to go. I wrote this to help with CSV data imports and [website microdata generation](https://github.com/dogweather/schema-dot-org).
|
18
15
|
|
19
|
-
And then execute:
|
20
|
-
|
21
|
-
$ bundle
|
22
|
-
|
23
|
-
Or install it yourself as:
|
24
|
-
|
25
|
-
$ gem install validated_object
|
26
16
|
|
27
17
|
## Usage
|
28
18
|
|
29
19
|
|
30
20
|
### Writing a self-validating object
|
31
21
|
|
32
|
-
All of the [ActiveModel::Validations](http://api.rubyonrails.org/classes/ActiveModel/Validations/ClassMethods.html#method-i-validates) are available, plus a new one, `TypeValidator`.
|
22
|
+
All of the [ActiveModel::Validations](http://api.rubyonrails.org/classes/ActiveModel/Validations/ClassMethods.html#method-i-validates) are available, plus a new one, `TypeValidator`.
|
33
23
|
|
34
24
|
```ruby
|
35
25
|
class Dog < ValidatedObject::Base
|
36
|
-
attr_accessor :name, :birthday
|
26
|
+
attr_accessor :name, :birthday # attr_reader is supported as well for read-only attributes
|
37
27
|
|
38
28
|
validates :name, presence: true
|
39
|
-
validates :birthday, type: Date, allow_nil: true
|
29
|
+
validates :birthday, type: Date, allow_nil: true # Strongly typed but optional
|
40
30
|
end
|
41
31
|
```
|
42
32
|
|
33
|
+
The `TypeValidator` is what enables `type: Date`, above. All classes can be checked, as well as a pseudo-class `Boolean`. E.g.:
|
34
|
+
|
35
|
+
```ruby
|
36
|
+
#...
|
37
|
+
validates :premium_membership, type: Boolean
|
38
|
+
#...
|
39
|
+
```
|
40
|
+
|
43
41
|
### Instantiating and automatically validating
|
44
42
|
|
45
43
|
```ruby
|
46
|
-
#
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
44
|
+
# This Dog instance validates itself at the end of instantiation.
|
45
|
+
spot = Dog.new(name: 'Spot')
|
46
|
+
```
|
47
|
+
|
48
|
+
```ruby
|
49
|
+
# We can also explicitly test for validity because all of
|
50
|
+
# ActiveModel::Validations is available.
|
51
|
+
spot.valid? # => true
|
52
|
+
|
53
|
+
spot.birthday = Date.new(2015, 1, 23)
|
54
|
+
spot.valid? # => true
|
55
|
+
```
|
51
56
|
|
52
|
-
|
53
|
-
dog1.valid? # => true
|
57
|
+
### Good error messages
|
54
58
|
|
55
|
-
|
56
|
-
|
59
|
+
Any of the standard Validations methods can be
|
60
|
+
used to test an instance, plus the custom `check_validations!` convenience method:
|
61
|
+
|
62
|
+
```ruby
|
63
|
+
spot.birthday = '2015-01-23'
|
64
|
+
spot.valid? # => false
|
65
|
+
spot.check_validations! # => ArgumentError: Birthday is class String, not Date
|
57
66
|
```
|
58
67
|
|
59
|
-
|
68
|
+
Note the clear, explicit error message. These are great when reading a log
|
69
|
+
file following a data import. It describes all the invalid conditions. Let's
|
70
|
+
test it by making another attribute invalid:
|
60
71
|
|
61
72
|
```ruby
|
62
|
-
|
63
|
-
|
64
|
-
dog1.check_validations! # => ArgumentError: Birthday is class String, not Date
|
73
|
+
spot.name = nil
|
74
|
+
spot.check_validations! # => ArgumentError: Name can't be blank; Birthday is class String, not Date
|
65
75
|
```
|
66
76
|
|
67
77
|
|
78
|
+
### Use in parsing data
|
79
|
+
|
80
|
+
I often use a validated object in a loop to import data, e.g.:
|
81
|
+
|
82
|
+
```ruby
|
83
|
+
# Import a CSV file of dogs
|
84
|
+
dogs = []
|
85
|
+
csv.next_row do |row|
|
86
|
+
begin
|
87
|
+
dogs << Dog.new(name: row.name)
|
88
|
+
rescue ArgumentError => e
|
89
|
+
logger.warn(e)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
```
|
93
|
+
|
94
|
+
The result is that `dogs` is an array of guaranteed valid Dog objects. And the
|
95
|
+
error log lists unparseable rows with good info for tracking down problems in
|
96
|
+
the data.
|
97
|
+
|
98
|
+
## Installation
|
99
|
+
|
100
|
+
Add this line to your application's Gemfile:
|
101
|
+
|
102
|
+
```ruby
|
103
|
+
gem 'validated_object'
|
104
|
+
```
|
105
|
+
|
106
|
+
And then execute:
|
107
|
+
|
108
|
+
$ bundle
|
109
|
+
|
110
|
+
Or install it yourself as:
|
111
|
+
|
112
|
+
$ gem install validated_object
|
113
|
+
|
114
|
+
|
115
|
+
|
68
116
|
## Development
|
69
117
|
|
70
|
-
(TODO: Verify these instructions.) After checking out the repo, run `bin/setup`
|
118
|
+
(TODO: Verify these instructions.) After checking out the repo, run `bin/setup`
|
119
|
+
to install dependencies. Then, run `rake spec` to run the tests. You can also
|
120
|
+
run `bin/console` for an interactive prompt that will allow you to experiment.
|
71
121
|
|
72
|
-
To install this gem onto your local machine, run `bundle exec rake install`. To
|
122
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To
|
123
|
+
release a new version, update the version number in `version.rb`, and then run
|
124
|
+
`bundle exec rake release`, which will create a git tag for the version, push
|
125
|
+
git commits and tags, and push the `.gem` file to
|
126
|
+
[rubygems.org](https://rubygems.org).
|
73
127
|
|
74
128
|
## Contributing
|
75
129
|
|
76
|
-
Bug reports and pull requests are welcome on GitHub at
|
130
|
+
Bug reports and pull requests are welcome on GitHub at
|
131
|
+
https://github.com/dogweather/validated_object.
|
77
132
|
|
78
133
|
|
79
134
|
## License
|
data/lib/validated_object.rb
CHANGED
@@ -21,9 +21,7 @@ module ValidatedObject
|
|
21
21
|
# @example Instantiating and automatically validating
|
22
22
|
# # The dog1 instance validates itself at the end of instantiation.
|
23
23
|
# # Here, it succeeds and so doesn't raise an exception.
|
24
|
-
# dog1 = Dog.new
|
25
|
-
# d.name = 'Spot'
|
26
|
-
# end
|
24
|
+
# dog1 = Dog.new name: 'Spot'
|
27
25
|
#
|
28
26
|
# # We can also explicitly test for validity
|
29
27
|
# dog1.valid? # => true
|
@@ -42,19 +40,24 @@ module ValidatedObject
|
|
42
40
|
class Base
|
43
41
|
include ActiveModel::Validations
|
44
42
|
|
43
|
+
EMPTY_HASH = {}.freeze
|
44
|
+
|
45
45
|
# Implements a pseudo-boolean class.
|
46
46
|
class Boolean
|
47
47
|
end
|
48
48
|
|
49
49
|
# Instantiate and validate a new object.
|
50
|
-
#
|
51
|
-
#
|
52
|
-
# for configuration.
|
50
|
+
# @example
|
51
|
+
# maru = Dog.new(birthday: Date.today, name: 'Maru')
|
53
52
|
#
|
54
53
|
# @raise [ArgumentError] if the object is not valid at the
|
55
|
-
# end of initialization.
|
56
|
-
def initialize
|
57
|
-
|
54
|
+
# end of initialization or `attributes` is not a Hash.
|
55
|
+
def initialize(attributes=EMPTY_HASH)
|
56
|
+
raise ArgumentError, "#{attributes} is not a Hash" unless attributes.is_a?(Hash)
|
57
|
+
|
58
|
+
attributes.keys.each do |key|
|
59
|
+
self.instance_variable_set "@#{key}".to_sym, attributes.fetch(key)
|
60
|
+
end
|
58
61
|
check_validations!
|
59
62
|
self
|
60
63
|
end
|
@@ -73,8 +76,8 @@ module ValidatedObject
|
|
73
76
|
# @example Ensure that weight is a number
|
74
77
|
# class Dog < ValidatedObject::Base
|
75
78
|
# attr_accessor :weight, :neutered
|
76
|
-
# validates :weight, type: Numeric
|
77
|
-
# validates :neutered, type: Boolean
|
79
|
+
# validates :weight, type: Numeric # Typed and required
|
80
|
+
# validates :neutered, type: Boolean, allow_nil: true # Typed but optional
|
78
81
|
# end
|
79
82
|
class TypeValidator < ActiveModel::EachValidator
|
80
83
|
# @return [nil]
|
@@ -87,7 +90,7 @@ module ValidatedObject
|
|
87
90
|
return if value.is_a?(expected_class)
|
88
91
|
end
|
89
92
|
|
90
|
-
msg = options[:message] || "is
|
93
|
+
msg = options[:message] || "is a #{value.class}, not a #{expected_class}"
|
91
94
|
record.errors.add attribute, msg
|
92
95
|
end
|
93
96
|
end
|
data/script/demo.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'date'
|
2
|
+
require 'validated_object'
|
3
|
+
|
4
|
+
class Dog < ValidatedObject::Base
|
5
|
+
attr_reader :name, :birthday
|
6
|
+
validates :name, presence: true
|
7
|
+
validates :birthday, type: Date, allow_nil: true
|
8
|
+
end
|
9
|
+
|
10
|
+
phoebe = Dog.new(name: 'Phoebe')
|
11
|
+
puts phoebe.inspect
|
12
|
+
|
13
|
+
maru = Dog.new(birthday: Date.today, name: 'Maru')
|
14
|
+
puts maru.inspect
|
15
|
+
|
16
|
+
paris = Dog.new
|
17
|
+
puts paris.inspect
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: validated_object
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Robb Shecter
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2018-02-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -85,6 +85,7 @@ files:
|
|
85
85
|
- bin/setup
|
86
86
|
- lib/validated_object.rb
|
87
87
|
- lib/validated_object/version.rb
|
88
|
+
- script/demo.rb
|
88
89
|
- validated_object.gemspec
|
89
90
|
homepage: https://github.com/dogweather/validated_object
|
90
91
|
licenses:
|
@@ -107,7 +108,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
107
108
|
version: '0'
|
108
109
|
requirements: []
|
109
110
|
rubyforge_project:
|
110
|
-
rubygems_version: 2.
|
111
|
+
rubygems_version: 2.7.6
|
111
112
|
signing_key:
|
112
113
|
specification_version: 4
|
113
114
|
summary: Self-validating plain Ruby objects.
|