validated_object 2.2.0 → 2.3.1
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/.github/workflows/ruby.yml +37 -0
- data/README.md +46 -6
- data/lib/validated_object/simplified_api.rb +18 -0
- data/lib/validated_object/version.rb +1 -1
- data/lib/validated_object.rb +8 -0
- data/validated_object.gemspec +2 -0
- metadata +6 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 03a54694b8208e1e788cd55ece182bacdbfa75f3389db8c0dcc8902df92d9822
|
4
|
+
data.tar.gz: 03c58a85faa371f663201c0deb0e7ed8cb021f35aae8d3568e18f24e7db09c59
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9f3bf8d6e81b2359e60f830d493e0a4fed9997bc21fa21c33f838794300e1b97514999ab42fb478a5cd22562ec89aa0dcfddf3a2c127b6b804f9f5f34faaea11
|
7
|
+
data.tar.gz: 5f05239f7150ffc10dc11544717298ec6500804ba4ab764cc8ba1dcb0bf1c6af7dfe59c927c829183902b575b2133ebc5278d2b1b9a3d8cd701dda8fd7a08f4d
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# This workflow uses actions that are not certified by GitHub.
|
2
|
+
# They are provided by a third-party and are governed by
|
3
|
+
# separate terms of service, privacy policy, and support
|
4
|
+
# documentation.
|
5
|
+
# This workflow will download a prebuilt Ruby version, install dependencies and run tests with Rake
|
6
|
+
# For more information see: https://github.com/marketplace/actions/setup-ruby-jruby-and-truffleruby
|
7
|
+
|
8
|
+
name: Ruby
|
9
|
+
|
10
|
+
on:
|
11
|
+
push:
|
12
|
+
branches: [ "master" ]
|
13
|
+
pull_request:
|
14
|
+
branches: [ "master" ]
|
15
|
+
|
16
|
+
permissions:
|
17
|
+
contents: read
|
18
|
+
|
19
|
+
jobs:
|
20
|
+
test:
|
21
|
+
|
22
|
+
runs-on: ubuntu-latest
|
23
|
+
strategy:
|
24
|
+
matrix:
|
25
|
+
ruby-version: ['3.1', '3.2', '3.3', '3.4']
|
26
|
+
|
27
|
+
steps:
|
28
|
+
- uses: actions/checkout@v3
|
29
|
+
|
30
|
+
- name: Set up Ruby
|
31
|
+
uses: ruby/setup-ruby@v1
|
32
|
+
with:
|
33
|
+
ruby-version: ${{ matrix.ruby-version }}
|
34
|
+
bundler-cache: true # runs 'bundle install' and caches installed gems automatically
|
35
|
+
|
36
|
+
- name: Run tests
|
37
|
+
run: bundle exec rake
|
data/README.md
CHANGED
@@ -1,8 +1,22 @@
|
|
1
|
-
[](https://badge.fury.io/rb/validated_object)
|
2
|
-
|
1
|
+
[](https://badge.fury.io/rb/validated_object)
|
3
2
|
# ValidatedObject
|
4
3
|
|
5
|
-
Plain Old Ruby
|
4
|
+
`Plain Old Ruby` + `Rails Validations` = **self-checking Ruby objects**.
|
5
|
+
|
6
|
+
## Example: A `Person` class that ensures its `name` isn't blank (nil or empty string):
|
7
|
+
|
8
|
+
```ruby
|
9
|
+
class Person < ValidatedObject::Base
|
10
|
+
attr_reader :name
|
11
|
+
validates :name, presence: true
|
12
|
+
end
|
13
|
+
|
14
|
+
# Instantiating it runs the validations.
|
15
|
+
me = Person.new(name: 'Robb')
|
16
|
+
you = Person.new(name: '') # => ArgumentError: "Name can't be blank"
|
17
|
+
```
|
18
|
+
|
19
|
+
Note how Person's two lines of code are nothing new: `attr_reader` is standard Ruby. [`validates`](https://guides.rubyonrails.org/active_record_validations.html) is standard Rails. I use classes like these as Data Transfer Objects at my system boundaries.
|
6
20
|
|
7
21
|
|
8
22
|
## Goals
|
@@ -11,7 +25,7 @@ Plain Old Ruby Objects + Rails Validations = **self-checking Ruby objects**.
|
|
11
25
|
* Clean, minimal syntax
|
12
26
|
|
13
27
|
This is a small layer around
|
14
|
-
[ActiveModel::Validations](http://api.rubyonrails.org/classes/ActiveModel/Validations/ClassMethods.html#method-i-validates). (About
|
28
|
+
[ActiveModel::Validations](http://api.rubyonrails.org/classes/ActiveModel/Validations/ClassMethods.html#method-i-validates). (About 25 lines of code.) So if you know how to use [Rails Validations](https://guides.rubyonrails.org/active_record_validations.html), you're good to go. I wrote this to help with CSV data imports and [website structured data](https://github.com/public-law/schema-dot-org).
|
15
29
|
|
16
30
|
|
17
31
|
## Usage
|
@@ -24,7 +38,7 @@ All of the [ActiveModel::Validations](http://api.rubyonrails.org/classes/ActiveM
|
|
24
38
|
```ruby
|
25
39
|
class Dog < ValidatedObject::Base
|
26
40
|
# Plain old Ruby
|
27
|
-
attr_accessor :name, :birthday
|
41
|
+
attr_accessor :name, :birthday
|
28
42
|
|
29
43
|
# Plain old Rails
|
30
44
|
validates :name, presence: true
|
@@ -34,6 +48,32 @@ class Dog < ValidatedObject::Base
|
|
34
48
|
end
|
35
49
|
```
|
36
50
|
|
51
|
+
Alternatively, we could make it immutable with Ruby's [attr_reader](https://bootrails.com/blog/ruby-attr-accessor-attr-writer-attr-reader/#2-attr_reader-attr_writer--attr_accessor):
|
52
|
+
|
53
|
+
```ruby
|
54
|
+
class ImmutableDog < ValidatedObject::Base
|
55
|
+
attr_reader :name, :birthday
|
56
|
+
|
57
|
+
validates :name, presence: true
|
58
|
+
validates :birthday, type: Date, allow_nil: true
|
59
|
+
end
|
60
|
+
```
|
61
|
+
|
62
|
+
And again, that `ImmutableDog` consists of one line of plain Ruby and two lines of standard Rails validations.
|
63
|
+
|
64
|
+
### `attr_reader` followed by `validates` is such a common pattern that there's a DSL which wraps them up into one call: `validates_attr`.
|
65
|
+
|
66
|
+
Here's the immutable version of `Dog` re-written with the new, simplified DSL:
|
67
|
+
|
68
|
+
```ruby
|
69
|
+
class ImmutableDog < ValidatedObject::Base
|
70
|
+
validates_attr :name, presence: true
|
71
|
+
validates_attr :birthday, type: Date, allow_nil: true
|
72
|
+
end
|
73
|
+
```
|
74
|
+
|
75
|
+
### About that `type:` check
|
76
|
+
|
37
77
|
The included `TypeValidator` is what enables `type: Date`, above. All classes can be checked, as well as a pseudo-class `Boolean`. E.g.:
|
38
78
|
|
39
79
|
```ruby
|
@@ -101,7 +141,7 @@ the data.
|
|
101
141
|
|
102
142
|
### Use in code generation
|
103
143
|
|
104
|
-
My [Schema.org
|
144
|
+
My [Schema.org structured data gem](https://github.com/public-law/schema-dot-org) uses ValidatedObjects to recursively create well formed HTML / JSON-LD.
|
105
145
|
|
106
146
|
## Installation
|
107
147
|
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require "active_support/concern"
|
2
|
+
|
3
|
+
# Enable a simplified API for the common case of
|
4
|
+
# read-only ValidatedObjects.
|
5
|
+
module ValidatedObject
|
6
|
+
module SimplifiedApi
|
7
|
+
extend ActiveSupport::Concern
|
8
|
+
|
9
|
+
class_methods do
|
10
|
+
# Simply delegate to `attr_reader` and `validates`.
|
11
|
+
def validated_attr(attribute, *options)
|
12
|
+
attr_reader attribute
|
13
|
+
validates attribute, *options
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|
data/lib/validated_object.rb
CHANGED
@@ -4,6 +4,8 @@
|
|
4
4
|
require 'active_model'
|
5
5
|
require 'sorbet-runtime'
|
6
6
|
require 'validated_object/version'
|
7
|
+
require 'validated_object/simplified_api'
|
8
|
+
|
7
9
|
|
8
10
|
module ValidatedObject
|
9
11
|
# @abstract Subclass and add `attr_accessor` and validations
|
@@ -43,6 +45,7 @@ module ValidatedObject
|
|
43
45
|
# @see http://www.rubyinside.com/rails-3-0s-activemodel-how-to-give-ruby-classes-some-activerecord-magic-2937.html Rails 3.0′s ActiveModel: How To Give Ruby Classes Some ActiveRecord Magic, Peter Cooper
|
44
46
|
class Base
|
45
47
|
include ActiveModel::Validations
|
48
|
+
include SimplifiedApi
|
46
49
|
extend T::Sig
|
47
50
|
|
48
51
|
SymbolHash = T.type_alias { T::Hash[Symbol, T.untyped] }
|
@@ -70,6 +73,11 @@ module ValidatedObject
|
|
70
73
|
nil
|
71
74
|
end
|
72
75
|
|
76
|
+
def validated_attr(attribute_name, **validation_options)
|
77
|
+
attr_reader attribute_name
|
78
|
+
validates attribute_name, validation_options
|
79
|
+
end
|
80
|
+
|
73
81
|
# Run any validations and raise an error if invalid.
|
74
82
|
#
|
75
83
|
# @raise [ArgumentError] if any validations fail.
|
data/validated_object.gemspec
CHANGED
@@ -5,6 +5,8 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
5
5
|
require 'validated_object/version'
|
6
6
|
|
7
7
|
Gem::Specification.new do |spec|
|
8
|
+
spec.required_ruby_version = '>= 3.1'
|
9
|
+
|
8
10
|
spec.name = 'validated_object'
|
9
11
|
spec.version = ValidatedObject::VERSION
|
10
12
|
spec.authors = ['Robb Shecter']
|
metadata
CHANGED
@@ -1,14 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: validated_object
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.3.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Robb Shecter
|
8
|
-
autorequire:
|
9
8
|
bindir: exe
|
10
9
|
cert_chain: []
|
11
|
-
date:
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
12
11
|
dependencies:
|
13
12
|
- !ruby/object:Gem::Dependency
|
14
13
|
name: rake
|
@@ -87,6 +86,7 @@ executables: []
|
|
87
86
|
extensions: []
|
88
87
|
extra_rdoc_files: []
|
89
88
|
files:
|
89
|
+
- ".github/workflows/ruby.yml"
|
90
90
|
- ".gitignore"
|
91
91
|
- ".rspec"
|
92
92
|
- ".travis.yml"
|
@@ -98,6 +98,7 @@ files:
|
|
98
98
|
- bin/console
|
99
99
|
- bin/setup
|
100
100
|
- lib/validated_object.rb
|
101
|
+
- lib/validated_object/simplified_api.rb
|
101
102
|
- lib/validated_object/version.rb
|
102
103
|
- script/demo.rb
|
103
104
|
- sorbet/config
|
@@ -124,7 +125,6 @@ licenses:
|
|
124
125
|
- MIT
|
125
126
|
metadata:
|
126
127
|
allowed_push_host: https://rubygems.org
|
127
|
-
post_install_message:
|
128
128
|
rdoc_options: []
|
129
129
|
require_paths:
|
130
130
|
- lib
|
@@ -132,15 +132,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
132
132
|
requirements:
|
133
133
|
- - ">="
|
134
134
|
- !ruby/object:Gem::Version
|
135
|
-
version: '
|
135
|
+
version: '3.1'
|
136
136
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
137
137
|
requirements:
|
138
138
|
- - ">="
|
139
139
|
- !ruby/object:Gem::Version
|
140
140
|
version: '0'
|
141
141
|
requirements: []
|
142
|
-
rubygems_version: 3.
|
143
|
-
signing_key:
|
142
|
+
rubygems_version: 3.6.9
|
144
143
|
specification_version: 4
|
145
144
|
summary: Self-validating plain Ruby objects.
|
146
145
|
test_files: []
|