Skip to content
This repository was archived by the owner on Sep 22, 2025. It is now read-only.

Commit c694ab1

Browse files
authored
Revert default behavior for value to validate (mirego#64)
1 parent 0b6cbe1 commit c694ab1

File tree

3 files changed

+33
-3
lines changed

3 files changed

+33
-3
lines changed

README.md

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ user.profile_invalid_json # => '{invalid JSON":}'
7070
| Option | Description |
7171
| ---------- | ------------------------------------------------------------------------------------------------------------------------------ |
7272
| `:schema` | The JSON schema to validate the data against (see **Schema** section) |
73+
| `:value` | The actual value to use when validating (see **Value** section) |
7374
| `:message` | The ActiveRecord message added to the record errors (see **Message** section) |
7475
| `:options` | A `Hash` of [`json_schemer`](https://github.com/davishmcclurg/json_schemer#options)-supported options to pass to the validator |
7576

@@ -111,6 +112,34 @@ class User < ActiveRecord::Base
111112
end
112113
```
113114

115+
##### Value
116+
117+
By default, the validator will use the “getter” method to the fetch attribute
118+
value and validate the schema against it.
119+
120+
```ruby
121+
# Will validate `self.foo`
122+
validates :foo, json: { schema: SCHEMA }
123+
```
124+
125+
But you can change this behavior if the getter method doesn’t return raw JSON data (a `Hash`):
126+
127+
```ruby
128+
# Will validate `self[:foo]`
129+
validates :foo, json: { schema: SCHEMA, value: ->(record, _, _) { record[:foo] } }
130+
```
131+
132+
You could also implement a “raw getter” if you want to avoid the `value` option:
133+
134+
```ruby
135+
# Will validate `self[:foo]`
136+
validates :raw_foo, json: { schema: SCHEMA }
137+
138+
def raw_foo
139+
self[:foo]
140+
end
141+
```
142+
114143
##### Message
115144

116145
Like any other ActiveModel validation, you can specify either a `Symbol` or

lib/active_record/json_validator/validator.rb

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ def initialize(options)
55
options.reverse_merge!(message: :invalid_json)
66
options.reverse_merge!(schema: nil)
77
options.reverse_merge!(options: {})
8+
options.reverse_merge!(value: ->(_record, _attribute, value) { value })
89
@attributes = options[:attributes]
910

1011
super
@@ -13,9 +14,9 @@ def initialize(options)
1314
end
1415

1516
# Validate the JSON value with a JSON schema path or String
16-
def validate_each(record, attribute, _value)
17+
def validate_each(record, attribute, value)
1718
# Get the _actual_ attribute value, not the getter method value
18-
value = record[attribute]
19+
value = options.fetch(:value).call(record, attribute, value)
1920

2021
# Validate value with JSON Schemer
2122
errors = JSONSchemer.schema(schema(record), **options.fetch(:options)).validate(value).to_a

spec/json_validator_spec.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
serialize :other_data, JSON
2929
validates :data, json: { schema: schema, message: ->(errors) { errors } }
3030
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 } }
31+
validates :smart_data, json: { value: ->(record, _, _) { record[:smart_data] }, schema: schema, message: ->(errors) { errors } }
3232

3333
def smart_data
3434
OpenStruct.new(self[:smart_data])

0 commit comments

Comments
 (0)