Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/mirego/activerecord_json_validator
🔩 ActiveRecord::JSONValidator makes it easy to validate JSON attributes against a JSON schema.
https://github.com/mirego/activerecord_json_validator
activemodel activerecord json-schema
Last synced: 4 days ago
JSON representation
🔩 ActiveRecord::JSONValidator makes it easy to validate JSON attributes against a JSON schema.
- Host: GitHub
- URL: https://github.com/mirego/activerecord_json_validator
- Owner: mirego
- License: bsd-3-clause
- Created: 2013-11-15T18:46:57.000Z (about 11 years ago)
- Default Branch: master
- Last Pushed: 2024-04-03T18:00:06.000Z (10 months ago)
- Last Synced: 2025-01-10T18:07:23.919Z (11 days ago)
- Topics: activemodel, activerecord, json-schema
- Language: Ruby
- Homepage: https://open.mirego.com
- Size: 107 KB
- Stars: 415
- Watchers: 51
- Forks: 61
- Open Issues: 14
-
Metadata Files:
- Readme: README.md
- License: LICENSE.md
Awesome Lists containing this project
- awesome-list - activerecord_json_validator
README
ActiveRecord::JSONValidator
makes it easy to validate
JSON attributes against a JSON schema.
---
## Installation
Add this line to your application's Gemfile:
```ruby
gem 'activerecord_json_validator', '~> 3.0.0'
```## Usage
### JSON Schema
Schemas should be a JSON file
```json
{
"type": "object",
"$schema": "http://json-schema.org/draft-04/schema#",
"properties": {
"city": { "type": "string" },
"country": { "type": "string" }
},
"required": ["country"]
}
```### Ruby
```ruby
create_table "users" do |t|
t.string "name"
t.json "profile" # First-class JSON with PostgreSQL, yo.
endclass User < ActiveRecord::Base
# Constants
PROFILE_JSON_SCHEMA = Rails.root.join('config', 'schemas', 'profile.json')# Validations
validates :name, presence: true
validates :profile, presence: true, json: { schema: PROFILE_JSON_SCHEMA }
enduser = User.new(name: 'Samuel Garneau', profile: { city: 'Quebec City' })
user.valid? # => falseuser = User.new(name: 'Samuel Garneau', profile: { city: 'Quebec City', country: 'Canada' })
user.valid? # => trueuser = User.new(name: 'Samuel Garneau', profile: '{invalid JSON":}')
user.valid? # => false
user.profile_invalid_json # => '{invalid JSON":}'
```#### Options
| Option | Description |
| ---------- | ------------------------------------------------------------------------------------------------------------------------------ |
| `:schema` | The JSON schema to validate the data against (see **Schema** section) |
| `:value` | The actual value to use when validating (see **Value** section) |
| `:message` | The ActiveRecord message added to the record errors (see **Message** section) |
| `:options` | A `Hash` of [`json_schemer`](https://github.com/davishmcclurg/json_schemer#options)-supported options to pass to the validator |##### Schema
`ActiveRecord::JSONValidator` uses the [json_schemer](https://github.com/davishmcclurg/json_schemer) gem to validate the JSON
data against a JSON schema.Additionally, you can use a `Symbol` or a `Proc`. Both will be executed in the
context of the validated record (`Symbol` will be sent as a method and the
`Proc` will be `instance_exec`ed)```ruby
class User < ActiveRecord::Base
# Constants
PROFILE_REGULAR_JSON_SCHEMA = Rails.root.join('config', 'schemas', 'profile.json_schema')
PROFILE_ADMIN_JSON_SCHEMA = Rails.root.join('config', 'schemas', 'profile_admin.json_schema')# Validations
validates :profile, presence: true, json: { schema: lambda { dynamic_profile_schema } } # `schema: :dynamic_profile_schema` would also workdef dynamic_profile_schema
admin? ? PROFILE_ADMIN_JSON_SCHEMA : PROFILE_REGULAR_JSON_SCHEMA
end
end
```The schema is passed to the `JSONSchemer.schema` function, so it can be anything supported by it:
```ruby
class User < ActiveRecord::Base
# Constants
JSON_SCHEMA = Rails.root.join('config', 'schemas', 'profile.json_schema')
# JSON_SCHEMA = { 'type' => 'object', 'properties' => { 'foo' => { 'type' => 'integer', 'minimum' => 3 } } }
# JSON_SCHEMA = '{"type":"object","properties":{"foo":{"type":"integer","minimum":3}}}'# Validations
validates :profile, presence: true, json: { schema: JSON_SCHEMA }
end
```##### Value
By default, the validator will use the “getter” method to the fetch attribute
value and validate the schema against it.```ruby
# Will validate `self.foo`
validates :foo, json: { schema: SCHEMA }
```But you can change this behavior if the getter method doesn’t return raw JSON data (a `Hash`):
```ruby
# Will validate `self[:foo]`
validates :foo, json: { schema: SCHEMA, value: ->(record, _, _) { record[:foo] } }
```You could also implement a “raw getter” if you want to avoid the `value` option:
```ruby
# Will validate `self[:foo]`
validates :raw_foo, json: { schema: SCHEMA }def raw_foo
self[:foo]
end
```##### Message
Like any other ActiveModel validation, you can specify either a `Symbol` or
`String` value for the `:message` option. The default value is `:invalid_json`.However, you can also specify a `Proc` that returns an array of errors. The
`Proc` will be called with a single argument — an array of errors returned by
the JSON schema validator. So, if you’d like to add each of these errors as
a first-level error for the record, you can do this:```ruby
class User < ActiveRecord::Base
# Validations
validates :profile, presence: true, json: { message: ->(errors) { errors }, schema: 'foo.json_schema' }
enduser = User.new.tap(&:valid?)
user.errors.full_messages
# => [
# 'The property '#/email' of type Fixnum did not match the following type: string in schema 2d44293f-cd9d-5dca-8a6a-fb9db1de722b#',
# 'The property '#/full_name' of type Fixnum did not match the following type: string in schema 2d44293f-cd9d-5dca-8a6a-fb9db1de722b#',
# ]
```## Development
The tests require a database. We've provided a simple `docker-compose.yml` that will make
it trivial to run the tests against PostgreSQL. Simply run `docker compose up -d`
followed by `rake spec`. When you're done, run `docker compose down` to stop the database.In order to use another database, simply define the `DATABASE_URL` environment variable
appropriately.## License
`ActiveRecord::JSONValidator` is © 2013-2024 [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.
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.
## About Mirego
[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).
We also [love open-source software](https://open.mirego.com) and we try to give back to the community as much as we can.