activerecord_json_validator 2.1.0 → 2.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.
- checksums.yaml +4 -4
- data/.github/workflows/ci.yaml +37 -0
- data/.rubocop.yml +5 -0
- data/LICENSE.md +1 -1
- data/README.md +24 -10
- data/activerecord_json_validator.gemspec +2 -2
- data/lib/active_record/json_validator/validator.rb +5 -1
- data/lib/active_record/json_validator/version.rb +1 -1
- data/spec/json_validator_spec.rb +17 -3
- data/spec/spec_helper.rb +0 -1
- data/spec/support/macros/database/database_adapter.rb +1 -1
- data/spec/support/macros/database/mysql_adapter.rb +0 -9
- data/spec/support/macros/database/postgresql_adapter.rb +0 -9
- metadata +25 -29
- data/.travis.yml +0 -41
- data/gemfiles/Gemfile.activerecord-4.2.x +0 -6
- data/gemfiles/Gemfile.activerecord-5.0.x +0 -5
- data/gemfiles/Gemfile.activerecord-6.0.x +0 -5
- data/gemfiles/Gemfile.activerecord-7.0.x +0 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 79e0a6948c155c358b3345637b6df84dc3b77ac1ea22ded1db53b35eefa4ad7c
|
4
|
+
data.tar.gz: 1a4c6092ee7635dd0b43767d08272a5b389c10ce9daa7ff379e89e04d4ee6766
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1f4f46c2db2c1b5f808fc98e003c4728b07a958a233218b1c565cb71a0bcf50118b7c1fb921735b4ee4e071f51fe458dca0e85e2267f262f30815c7b816afaac
|
7
|
+
data.tar.gz: 823a2e6c404e9939976177d6c0221d2ed1d0762315ec1767721492ce764302f734c0563c4e04d2f1ccf114ac40aeeb07027550dc48f1977616df548882fcf4d7
|
@@ -0,0 +1,37 @@
|
|
1
|
+
name: CI
|
2
|
+
|
3
|
+
on:
|
4
|
+
push:
|
5
|
+
branches:
|
6
|
+
- master
|
7
|
+
pull_request:
|
8
|
+
branches:
|
9
|
+
- '**'
|
10
|
+
|
11
|
+
jobs:
|
12
|
+
ci:
|
13
|
+
runs-on: ubuntu-latest
|
14
|
+
|
15
|
+
services:
|
16
|
+
db:
|
17
|
+
image: postgres:10.19
|
18
|
+
env:
|
19
|
+
POSTGRES_DB: activerecord_json_validator_test
|
20
|
+
POSTGRES_USER: postgres
|
21
|
+
POSTGRES_PASSWORD: postgres
|
22
|
+
ports: ['5432:5432']
|
23
|
+
options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5
|
24
|
+
|
25
|
+
env:
|
26
|
+
CANONICAL_HOST: localhost
|
27
|
+
DATABASE_URL: postgres://postgres:postgres@localhost/activerecord_json_validator_test
|
28
|
+
DB_ADAPTER: postgresql
|
29
|
+
|
30
|
+
steps:
|
31
|
+
- uses: actions/checkout@v2
|
32
|
+
- uses: ruby/setup-ruby@v1
|
33
|
+
with:
|
34
|
+
ruby-version: '2.7.5'
|
35
|
+
bundler-cache: true
|
36
|
+
- run: bundle exec rubocop
|
37
|
+
- run: bundle exec rake spec
|
data/.rubocop.yml
CHANGED
data/LICENSE.md
CHANGED
data/README.md
CHANGED
@@ -3,10 +3,10 @@
|
|
3
3
|
<img src="https://user-images.githubusercontent.com/11348/126779905-3468eb15-d554-46d5-925b-235f68169d86.png" alt="" />
|
4
4
|
</a>
|
5
5
|
<br />
|
6
|
-
<code>ActiveRecord::JSONValidator</code> makes it easy to validate<br /> JSON attributes against a <a href="
|
6
|
+
<code>ActiveRecord::JSONValidator</code> makes it easy to validate<br /> JSON attributes against a <a href="https://json-schema.org/">JSON schema</a>.
|
7
7
|
<br /><br />
|
8
|
-
<a href="https://rubygems.org/gems/activerecord_json_validator"><img src="
|
9
|
-
<a href="https://
|
8
|
+
<a href="https://rubygems.org/gems/activerecord_json_validator"><img src="https://img.shields.io/gem/v/activerecord_json_validator.svg" /></a>
|
9
|
+
<a href="https://github.com/mirego/activerecord_json_validator/actions/workflows/ci.yaml"><img src="https://github.com/mirego/activerecord_json_validator/actions/workflows/ci.yaml/badge.svg" /></a>
|
10
10
|
</p>
|
11
11
|
|
12
12
|
---
|
@@ -47,7 +47,7 @@ end
|
|
47
47
|
|
48
48
|
class User < ActiveRecord::Base
|
49
49
|
# Constants
|
50
|
-
PROFILE_JSON_SCHEMA =
|
50
|
+
PROFILE_JSON_SCHEMA = Rails.root.join('config', 'schemas', 'profile.json')
|
51
51
|
|
52
52
|
# Validations
|
53
53
|
validates :name, presence: true
|
@@ -85,8 +85,8 @@ context of the validated record (`Symbol` will be sent as a method and the
|
|
85
85
|
```ruby
|
86
86
|
class User < ActiveRecord::Base
|
87
87
|
# Constants
|
88
|
-
PROFILE_REGULAR_JSON_SCHEMA = Rails.root.join('config', 'schemas', 'profile.json_schema')
|
89
|
-
PROFILE_ADMIN_JSON_SCHEMA = Rails.root.join('config', 'schemas', 'profile_admin.json_schema')
|
88
|
+
PROFILE_REGULAR_JSON_SCHEMA = Rails.root.join('config', 'schemas', 'profile.json_schema')
|
89
|
+
PROFILE_ADMIN_JSON_SCHEMA = Rails.root.join('config', 'schemas', 'profile_admin.json_schema')
|
90
90
|
|
91
91
|
# Validations
|
92
92
|
validates :profile, presence: true, json: { schema: lambda { dynamic_profile_schema } } # `schema: :dynamic_profile_schema` would also work
|
@@ -97,6 +97,20 @@ class User < ActiveRecord::Base
|
|
97
97
|
end
|
98
98
|
```
|
99
99
|
|
100
|
+
The schema is passed to the `JSONSchemer.schema` function, so it can be anything supported by it:
|
101
|
+
|
102
|
+
```ruby
|
103
|
+
class User < ActiveRecord::Base
|
104
|
+
# Constants
|
105
|
+
JSON_SCHEMA = Rails.root.join('config', 'schemas', 'profile.json_schema')
|
106
|
+
# JSON_SCHEMA = { 'type' => 'object', 'properties' => { 'foo' => { 'type' => 'integer', 'minimum' => 3 } } }
|
107
|
+
# JSON_SCHEMA = '{"type":"object","properties":{"foo":{"type":"integer","minimum":3}}}'
|
108
|
+
|
109
|
+
# Validations
|
110
|
+
validates :profile, presence: true, json: { schema: JSON_SCHEMA }
|
111
|
+
end
|
112
|
+
```
|
113
|
+
|
100
114
|
##### Message
|
101
115
|
|
102
116
|
Like any other ActiveModel validation, you can specify either a `Symbol` or
|
@@ -123,12 +137,12 @@ user.errors.full_messages
|
|
123
137
|
|
124
138
|
## License
|
125
139
|
|
126
|
-
`ActiveRecord::JSONValidator` is © 2013-
|
140
|
+
`ActiveRecord::JSONValidator` is © 2013-2022 [Mirego](https://www.mirego.com) and may be freely distributed under the [New BSD license](https://opensource.org/licenses/BSD-3-Clause). See the [`LICENSE.md`](https://github.com/mirego/activerecord_json_validator/blob/master/LICENSE.md) file.
|
127
141
|
|
128
|
-
The tree logo is based on [this lovely icon](
|
142
|
+
The tree logo is based on [this lovely icon](https://thenounproject.com/term/tree/51004/) by [Sara Quintana](https://thenounproject.com/sara.quintana.75), from The Noun Project. Used under a [Creative Commons BY 3.0](https://creativecommons.org/licenses/by/3.0/) license.
|
129
143
|
|
130
144
|
## About Mirego
|
131
145
|
|
132
|
-
[Mirego](
|
146
|
+
[Mirego](https://www.mirego.com) is a team of passionate people who believe that work is a place where you can innovate and have fun. We're a team of [talented people](https://life.mirego.com) who imagine and build beautiful Web and mobile applications. We come together to share ideas and [change the world](https://www.mirego.org).
|
133
147
|
|
134
|
-
We also [love open-source software](
|
148
|
+
We also [love open-source software](https://open.mirego.com) and we try to give back to the community as much as we can.
|
@@ -22,10 +22,10 @@ Gem::Specification.new do |spec|
|
|
22
22
|
spec.add_development_dependency 'rake'
|
23
23
|
spec.add_development_dependency 'rspec', '~> 3.5'
|
24
24
|
spec.add_development_dependency 'pg'
|
25
|
-
spec.add_development_dependency 'mysql2'
|
26
25
|
spec.add_development_dependency 'activesupport', '>= 4.2.0', '< 8'
|
27
|
-
spec.add_development_dependency 'phare'
|
28
26
|
spec.add_development_dependency 'rubocop', '~> 0.28'
|
27
|
+
spec.add_development_dependency 'rubocop-rspec', '~> 1.44'
|
28
|
+
spec.add_development_dependency 'rubocop-standard', '~> 6.0'
|
29
29
|
|
30
30
|
spec.add_dependency 'json_schemer', '~> 0.2.18'
|
31
31
|
spec.add_dependency 'activerecord', '>= 4.2.0', '< 8'
|
@@ -13,7 +13,10 @@ class JsonValidator < ActiveModel::EachValidator
|
|
13
13
|
end
|
14
14
|
|
15
15
|
# Validate the JSON value with a JSON schema path or String
|
16
|
-
def validate_each(record, attribute,
|
16
|
+
def validate_each(record, attribute, _value)
|
17
|
+
# Get the _actual_ attribute value, not the getter method value
|
18
|
+
value = record[attribute]
|
19
|
+
|
17
20
|
# Validate value with JSON Schemer
|
18
21
|
errors = JSONSchemer.schema(schema(record), **options.fetch(:options)).validate(value).to_a
|
19
22
|
|
@@ -22,6 +25,7 @@ class JsonValidator < ActiveModel::EachValidator
|
|
22
25
|
|
23
26
|
# Add error message to the attribute
|
24
27
|
message(errors).each do |error|
|
28
|
+
error = error.is_a?(Hash) ? JSONSchemer::Errors.pretty(error) : error
|
25
29
|
record.errors.add(attribute, error, value: value)
|
26
30
|
end
|
27
31
|
end
|
data/spec/json_validator_spec.rb
CHANGED
@@ -9,6 +9,7 @@ describe JsonValidator do
|
|
9
9
|
run_migration do
|
10
10
|
create_table(:users, force: true) do |t|
|
11
11
|
t.text :data
|
12
|
+
t.json :smart_data
|
12
13
|
end
|
13
14
|
end
|
14
15
|
|
@@ -24,16 +25,29 @@ describe JsonValidator do
|
|
24
25
|
}
|
25
26
|
'
|
26
27
|
serialize :data, JSON
|
27
|
-
|
28
|
+
serialize :other_data, JSON
|
29
|
+
validates :data, json: { schema: schema, message: ->(errors) { errors } }
|
30
|
+
validates :other_data, json: { schema: schema, message: ->(errors) { errors.map { |error| error['details'].to_a.flatten.join(' ') } } }
|
31
|
+
validates :smart_data, json: { schema: schema, message: ->(errors) { errors } }
|
32
|
+
|
33
|
+
def smart_data
|
34
|
+
OpenStruct.new(self[:smart_data])
|
35
|
+
end
|
28
36
|
end
|
29
37
|
end
|
30
38
|
|
31
39
|
context 'with valid JSON data but schema errors' do
|
32
|
-
let(:user)
|
40
|
+
let(:user) do
|
41
|
+
User.new(
|
42
|
+
data: '{"city":"Quebec City"}',
|
43
|
+
other_data: '{"city":"Quebec City"}',
|
44
|
+
smart_data: { country: 'Canada', city: 'Quebec City' }
|
45
|
+
)
|
46
|
+
end
|
33
47
|
|
34
48
|
specify do
|
35
49
|
expect(user).not_to be_valid
|
36
|
-
expect(user.errors.full_messages).to eql(['Data missing_keys country'])
|
50
|
+
expect(user.errors.full_messages).to eql(['Data root is missing required keys: country', 'Other data missing_keys country'])
|
37
51
|
expect(user.data).to eql({ 'city' => 'Quebec City' })
|
38
52
|
expect(user.data_invalid_json).to be_nil
|
39
53
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -3,15 +3,6 @@
|
|
3
3
|
require_relative 'database_adapter'
|
4
4
|
|
5
5
|
class Mysql2Adapter < DatabaseAdapter
|
6
|
-
def database_configuration
|
7
|
-
{
|
8
|
-
adapter: 'mysql2',
|
9
|
-
database: @database,
|
10
|
-
username: 'travis',
|
11
|
-
encoding: 'utf8'
|
12
|
-
}
|
13
|
-
end
|
14
|
-
|
15
6
|
def reset_database!
|
16
7
|
ActiveRecord::Base.connection.execute("SELECT concat('DROP TABLE IF EXISTS ', table_name, ';') FROM information_schema.tables WHERE table_schema = '#{@database}';")
|
17
8
|
end
|
@@ -3,15 +3,6 @@
|
|
3
3
|
require_relative 'database_adapter'
|
4
4
|
|
5
5
|
class PostgresqlAdapter < DatabaseAdapter
|
6
|
-
def database_configuration
|
7
|
-
{
|
8
|
-
adapter: 'postgresql',
|
9
|
-
database: @database,
|
10
|
-
user: 'postgres',
|
11
|
-
schema_search_path: 'public'
|
12
|
-
}
|
13
|
-
end
|
14
|
-
|
15
6
|
def reset_database!
|
16
7
|
ActiveRecord::Base.connection.execute('drop schema public cascade;')
|
17
8
|
ActiveRecord::Base.connection.execute('create schema public;')
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: activerecord_json_validator
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.1.
|
4
|
+
version: 2.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Rémi Prévost
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-11-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -66,20 +66,6 @@ dependencies:
|
|
66
66
|
- - ">="
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '0'
|
69
|
-
- !ruby/object:Gem::Dependency
|
70
|
-
name: mysql2
|
71
|
-
requirement: !ruby/object:Gem::Requirement
|
72
|
-
requirements:
|
73
|
-
- - ">="
|
74
|
-
- !ruby/object:Gem::Version
|
75
|
-
version: '0'
|
76
|
-
type: :development
|
77
|
-
prerelease: false
|
78
|
-
version_requirements: !ruby/object:Gem::Requirement
|
79
|
-
requirements:
|
80
|
-
- - ">="
|
81
|
-
- !ruby/object:Gem::Version
|
82
|
-
version: '0'
|
83
69
|
- !ruby/object:Gem::Dependency
|
84
70
|
name: activesupport
|
85
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -101,33 +87,47 @@ dependencies:
|
|
101
87
|
- !ruby/object:Gem::Version
|
102
88
|
version: '8'
|
103
89
|
- !ruby/object:Gem::Dependency
|
104
|
-
name:
|
90
|
+
name: rubocop
|
105
91
|
requirement: !ruby/object:Gem::Requirement
|
106
92
|
requirements:
|
107
|
-
- - "
|
93
|
+
- - "~>"
|
108
94
|
- !ruby/object:Gem::Version
|
109
|
-
version: '0'
|
95
|
+
version: '0.28'
|
110
96
|
type: :development
|
111
97
|
prerelease: false
|
112
98
|
version_requirements: !ruby/object:Gem::Requirement
|
113
99
|
requirements:
|
114
|
-
- - "
|
100
|
+
- - "~>"
|
115
101
|
- !ruby/object:Gem::Version
|
116
|
-
version: '0'
|
102
|
+
version: '0.28'
|
117
103
|
- !ruby/object:Gem::Dependency
|
118
|
-
name: rubocop
|
104
|
+
name: rubocop-rspec
|
119
105
|
requirement: !ruby/object:Gem::Requirement
|
120
106
|
requirements:
|
121
107
|
- - "~>"
|
122
108
|
- !ruby/object:Gem::Version
|
123
|
-
version: '
|
109
|
+
version: '1.44'
|
124
110
|
type: :development
|
125
111
|
prerelease: false
|
126
112
|
version_requirements: !ruby/object:Gem::Requirement
|
127
113
|
requirements:
|
128
114
|
- - "~>"
|
129
115
|
- !ruby/object:Gem::Version
|
130
|
-
version: '
|
116
|
+
version: '1.44'
|
117
|
+
- !ruby/object:Gem::Dependency
|
118
|
+
name: rubocop-standard
|
119
|
+
requirement: !ruby/object:Gem::Requirement
|
120
|
+
requirements:
|
121
|
+
- - "~>"
|
122
|
+
- !ruby/object:Gem::Version
|
123
|
+
version: '6.0'
|
124
|
+
type: :development
|
125
|
+
prerelease: false
|
126
|
+
version_requirements: !ruby/object:Gem::Requirement
|
127
|
+
requirements:
|
128
|
+
- - "~>"
|
129
|
+
- !ruby/object:Gem::Version
|
130
|
+
version: '6.0'
|
131
131
|
- !ruby/object:Gem::Dependency
|
132
132
|
name: json_schemer
|
133
133
|
requirement: !ruby/object:Gem::Requirement
|
@@ -170,19 +170,15 @@ executables: []
|
|
170
170
|
extensions: []
|
171
171
|
extra_rdoc_files: []
|
172
172
|
files:
|
173
|
+
- ".github/workflows/ci.yaml"
|
173
174
|
- ".gitignore"
|
174
175
|
- ".rspec"
|
175
176
|
- ".rubocop.yml"
|
176
|
-
- ".travis.yml"
|
177
177
|
- Gemfile
|
178
178
|
- LICENSE.md
|
179
179
|
- README.md
|
180
180
|
- Rakefile
|
181
181
|
- activerecord_json_validator.gemspec
|
182
|
-
- gemfiles/Gemfile.activerecord-4.2.x
|
183
|
-
- gemfiles/Gemfile.activerecord-5.0.x
|
184
|
-
- gemfiles/Gemfile.activerecord-6.0.x
|
185
|
-
- gemfiles/Gemfile.activerecord-7.0.x
|
186
182
|
- lib/active_record/json_validator/validator.rb
|
187
183
|
- lib/active_record/json_validator/version.rb
|
188
184
|
- lib/activerecord_json_validator.rb
|
data/.travis.yml
DELETED
@@ -1,41 +0,0 @@
|
|
1
|
-
language: ruby
|
2
|
-
|
3
|
-
rvm:
|
4
|
-
- 2.4.6
|
5
|
-
- 2.6.3
|
6
|
-
- 2.7.5
|
7
|
-
|
8
|
-
gemfile:
|
9
|
-
- gemfiles/Gemfile.activerecord-4.2.x
|
10
|
-
- gemfiles/Gemfile.activerecord-5.0.x
|
11
|
-
- gemfiles/Gemfile.activerecord-6.0.x
|
12
|
-
- gemfiles/Gemfile.activerecord-7.0.x
|
13
|
-
|
14
|
-
matrix:
|
15
|
-
exclude:
|
16
|
-
- gemfile: gemfiles/Gemfile.activerecord-6.0.x
|
17
|
-
rvm: 2.4.6
|
18
|
-
- gemfile: gemfiles/Gemfile.activerecord-7.0.x
|
19
|
-
rvm: 2.4.6
|
20
|
-
- gemfile: gemfiles/Gemfile.activerecord-7.0.x
|
21
|
-
rvm: 2.6.3
|
22
|
-
- gemfile: gemfiles/Gemfile.activerecord-4.2.x
|
23
|
-
rvm: 2.7.5
|
24
|
-
|
25
|
-
sudo: false
|
26
|
-
|
27
|
-
services:
|
28
|
-
- mysql
|
29
|
-
- postgresql
|
30
|
-
|
31
|
-
env:
|
32
|
-
- DB_ADAPTER=mysql2
|
33
|
-
- DB_ADAPTER=postgresql
|
34
|
-
|
35
|
-
before_script:
|
36
|
-
- mysql -e 'create database activerecord_json_validator_test;'
|
37
|
-
- psql -c 'create database activerecord_json_validator_test;' -U postgres
|
38
|
-
|
39
|
-
script:
|
40
|
-
- 'echo "Checking code style" && bundle exec phare'
|
41
|
-
- 'echo "Running tests" && bundle exec rake spec'
|