activerecord_json_validator 0.3 → 0.4

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 22cf2432dfb4427ba383de56c603a6ab9a02ff74
4
- data.tar.gz: eb005d90645dcf4e6471d7bd784523d67146418d
3
+ metadata.gz: b48b4031de5f8c6acbebdf18140fcedba69ed87c
4
+ data.tar.gz: c378d6029f74ab611000db2ade4b785beec0f031
5
5
  SHA512:
6
- metadata.gz: 637ba361b8d482dbe0edea5e27a96a815af724b9cfa5a2cdf7504d0f7f64a26b0e82e3228ad34a044b3e5ea64129f36556889dfa23a6a8d01d22830feb706705
7
- data.tar.gz: 910b92a51b66a283b60a15d79854ca58c05104c786de9d0a7a578e21c9ef782c5a5e0bba46ef88df12aed68d5a80f6ec03e71156e4610751cd16dee254a05461
6
+ metadata.gz: 587e07e4a9fbb7dabc6e82dc880dd7069ee1eaf89b32f9523512d0d6e5ec5724e383f1e0301b2ef76c820b09a2370c59e7ed0e62d5fd4a919a2279b7ffda9e60
7
+ data.tar.gz: 6d8edfea72e360af096bf8abc94c8b9b56db6e4028f712e06488aa179a1dec59df06cf386bfe7bb986a779bba8ae3eabe67c552182c3cb59d0fab52046e59c9b
data/.rubocop.yml ADDED
@@ -0,0 +1,62 @@
1
+ AllCops:
2
+ Exclude:
3
+ - activerecord_json_validator.gemspec
4
+
5
+ Documentation:
6
+ Enabled: false
7
+
8
+ Encoding:
9
+ Enabled: false
10
+
11
+ LineLength:
12
+ Max: 200
13
+
14
+ AccessModifierIndentation:
15
+ EnforcedStyle: outdent
16
+
17
+ IfUnlessModifier:
18
+ Enabled: false
19
+
20
+ CaseIndentation:
21
+ IndentWhenRelativeTo: case
22
+ IndentOneStep: true
23
+
24
+ MethodLength:
25
+ CountComments: false
26
+ Max: 20
27
+
28
+ SignalException:
29
+ Enabled: false
30
+
31
+ ColonMethodCall:
32
+ Enabled: false
33
+
34
+ AsciiComments:
35
+ Enabled: false
36
+
37
+ RegexpLiteral:
38
+ Enabled: false
39
+
40
+ AssignmentInCondition:
41
+ Enabled: false
42
+
43
+ ParameterLists:
44
+ CountKeywordArgs: false
45
+
46
+ SingleLineBlockParams:
47
+ Methods:
48
+ - reduce:
49
+ - memo
50
+ - item
51
+
52
+ Metrics/AbcSize:
53
+ Enabled: false
54
+
55
+ Style/CollectionMethods:
56
+ Enabled: true
57
+
58
+ Style/SymbolArray:
59
+ Enabled: true
60
+
61
+ Style/ExtraSpacing:
62
+ Enabled: true
data/.travis.yml CHANGED
@@ -18,7 +18,9 @@ before_script:
18
18
  - mysql -e 'create database activerecord_json_validator_test;'
19
19
  - psql -c 'create database activerecord_json_validator_test;' -U postgres
20
20
 
21
- script: "echo 'DO IT' && bundle exec rake spec"
21
+ script:
22
+ - 'echo "Checking code style" && bundle exec phare'
23
+ - 'echo "Running tests" && bundle exec rake spec'
22
24
 
23
25
  addons:
24
26
  postgresql: 9.3
data/README.md CHANGED
@@ -56,6 +56,86 @@ user.valid? # => false
56
56
  user.profile_invalid_json # => '{invalid JSON":}'
57
57
  ```
58
58
 
59
+ #### Options
60
+
61
+ | Option | Description
62
+ |------------|-----------------------------------------------------
63
+ | `:schema` | The JSON schema to validate the data against (see **JSON schema option** section)
64
+ | `:message` | The ActiveRecord message added to the record errors (default: `:invalid_json`)
65
+
66
+ ##### JSON schema option
67
+
68
+ You can specify four kinds of value for the `:schema` option.
69
+
70
+ ###### A path to a file containing a JSON schema
71
+
72
+ ```ruby
73
+ class User < ActiveRecord::Base
74
+ # Constants
75
+ PROFILE_JSON_SCHEMA = Rails.root.join('config', 'schemas', 'profile.json_schema').to_s
76
+
77
+ # Validations
78
+ validates :profile, presence: true, json: { schema: PROFILE_JSON_SCHEMA }
79
+ end
80
+ ```
81
+
82
+ ###### A Ruby `Hash` representing a JSON schema
83
+
84
+ ```ruby
85
+ class User < ActiveRecord::Base
86
+ # Constants
87
+ PROFILE_JSON_SCHEMA = {
88
+ type: 'object',
89
+ :'$schema' => 'http://json-schema.org/draft-03/schema',
90
+ properties: {
91
+ city: { type: 'string', required: false },
92
+ country: { type: 'string', required: true }
93
+ }
94
+ }
95
+
96
+ # Validations
97
+ validates :profile, presence: true, json: { schema: PROFILE_JSON_SCHEMA }
98
+ end
99
+ ```
100
+
101
+ ###### A plain JSON schema as a Ruby `String`
102
+
103
+ ```ruby
104
+ class User < ActiveRecord::Base
105
+ # Constants
106
+ PROFILE_JSON_SCHEMA = '{
107
+ "type": "object",
108
+ "$schema": "http://json-schema.org/draft-03/schema",
109
+ "properties": {
110
+ "city": { "type": "string", "required": false },
111
+ "country": { "type": "string", "required": true }
112
+ }
113
+ }'
114
+
115
+ # Validations
116
+ validates :profile, presence: true, json: { schema: PROFILE_JSON_SCHEMA }
117
+ end
118
+ ```
119
+
120
+ ###### A lambda that will get evaluated in the context of the validated record
121
+
122
+ The lambda must return a valid value for the `:schema` option (file path, JSON `String` or Ruby `Hash`).
123
+
124
+ ```ruby
125
+ class User < ActiveRecord::Base
126
+ # Constants
127
+ PROFILE_REGULAR_JSON_SCHEMA = Rails.root.join('config', 'schemas', 'profile.json_schema').to_s
128
+ PROFILE_ADMIN_JSON_SCHEMA = Rails.root.join('config', 'schemas', 'profile_admin.json_schema').to_s
129
+
130
+ # Validations
131
+ validates :profile, presence: true, json: { schema: lambda { dynamic_profile_schema } }
132
+
133
+ def dynamic_profile_schema
134
+ admin? ? PROFILE_ADMIN_JSON_SCHEMA : PROFILE_REGULAR_JSON_SCHEMA
135
+ end
136
+ end
137
+ ```
138
+
59
139
  ## License
60
140
 
61
141
  `ActiveRecord::JSONValidator` is © 2013-2015 [Mirego](http://www.mirego.com) and may be freely distributed under the [New BSD license](http://opensource.org/licenses/BSD-3-Clause). See the [`LICENSE.md`](https://github.com/mirego/activerecord_json_validator/blob/master/LICENSE.md) file.
data/Rakefile CHANGED
@@ -12,7 +12,7 @@ end
12
12
 
13
13
  desc 'Start an IRB session with the gem'
14
14
  task :console do
15
- $:.unshift File.expand_path('..', __FILE__)
15
+ $LOAD_PATH.unshift File.expand_path('..', __FILE__)
16
16
  require 'activerecord_json_validator'
17
17
  require 'irb'
18
18
 
@@ -24,6 +24,8 @@ Gem::Specification.new do |spec|
24
24
  spec.add_development_dependency 'pg'
25
25
  spec.add_development_dependency 'mysql2'
26
26
  spec.add_development_dependency 'activesupport', '>= 4.1.0', '< 5'
27
+ spec.add_development_dependency 'phare'
28
+ spec.add_development_dependency 'rubocop', '~> 0.28'
27
29
 
28
30
  spec.add_dependency 'json-schema', '~> 2.5'
29
31
  spec.add_dependency 'activerecord', '>= 4.1.0', '< 5'
@@ -28,11 +28,15 @@ class JsonValidator < ActiveModel::EachValidator
28
28
  json_value = ''
29
29
  end
30
30
 
31
- errors = ::JSON::Validator.fully_validate(options.fetch(:schema), json_value)
31
+ # Validate value with JSON::Validator
32
+ schema = fetch_schema_for_record(record)
33
+ errors = ::JSON::Validator.fully_validate(schema, json_value)
32
34
 
33
- if errors.any? || record.send(:"#{attribute}_invalid_json").present?
34
- record.errors.add(attribute, options.fetch(:message), value: value)
35
- end
35
+ # Everything is good if we don’t have any errors and we got valid JSON value
36
+ return true if errors.empty? && record.send(:"#{attribute}_invalid_json").blank?
37
+
38
+ # Add error message to the attribute
39
+ record.errors.add(attribute, options.fetch(:message), value: value)
36
40
  end
37
41
 
38
42
  protected
@@ -51,10 +55,17 @@ protected
51
55
  super(args)
52
56
  rescue MultiJson::LoadError, JSON::ParserError
53
57
  @#{attribute}_invalid_json = args
54
- super(invalid_json: true)
58
+ super({})
55
59
  end
56
60
  end
57
61
  RUBY
58
62
  end
59
63
  end
64
+
65
+ def fetch_schema_for_record(record)
66
+ schema = options.fetch(:schema)
67
+ return schema unless schema.is_a?(Proc)
68
+
69
+ record.instance_exec(&schema)
70
+ end
60
71
  end
@@ -1,5 +1,5 @@
1
1
  module ActiveRecord
2
2
  module JSONValidator
3
- VERSION = '0.3'
3
+ VERSION = '0.4'
4
4
  end
5
5
  end
@@ -9,23 +9,36 @@ describe JsonValidator do
9
9
  end
10
10
  end
11
11
 
12
+ json_schema = schema
12
13
  spawn_model :User do
13
- schema = {
14
- type: 'object',
15
- :'$schema' => 'http://json-schema.org/draft-03/schema',
16
- properties: {
17
- city: { type: 'string', required: false },
18
- country: { type: 'string', required: true }
19
- }
20
- }
21
-
22
14
  serialize :profile, JSON
23
15
  validates :name, presence: true
24
- validates :profile, presence: true, json: { schema: schema }
16
+ validates :profile, presence: true, json: { schema: json_schema }
17
+
18
+ def dynamic_json_schema
19
+ {
20
+ type: 'object',
21
+ :'$schema' => 'http://json-schema.org/draft-03/schema',
22
+ properties: {
23
+ foo: { type: 'string', required: false },
24
+ bar: { type: 'string', required: true }
25
+ }
26
+ }
27
+ end
25
28
  end
26
29
  end
27
30
 
28
31
  let(:user) { User.create(attributes) }
32
+ let(:schema) do
33
+ {
34
+ type: 'object',
35
+ :'$schema' => 'http://json-schema.org/draft-03/schema',
36
+ properties: {
37
+ city: { type: 'string', required: false },
38
+ country: { type: 'string', required: true }
39
+ }
40
+ }
41
+ end
29
42
 
30
43
  context 'with blank JSON value' do
31
44
  let(:attributes) { { name: 'Samuel Garneau', profile: {} } }
@@ -61,7 +74,23 @@ describe JsonValidator do
61
74
 
62
75
  specify do
63
76
  expect(user).to_not be_valid
77
+ expect(user.profile).to eql({})
64
78
  expect(user.profile_invalid_json).to eql('foo:}bar')
65
79
  end
66
80
  end
81
+
82
+ context 'with lambda schema option' do
83
+ # The dynamic schema makes `country` and `city` keys mandatory
84
+ let(:schema) { -> { dynamic_json_schema } }
85
+
86
+ context 'with valid JSON value' do
87
+ let(:attributes) { { name: 'Samuel Garneau', profile: { foo: 'bar', bar: 'foo' } } }
88
+ it { expect(user).to be_valid }
89
+ end
90
+
91
+ context 'with invalid JSON value' do
92
+ let(:attributes) { { name: 'Samuel Garneau', profile: {} } }
93
+ it { expect(user).not_to be_valid }
94
+ end
95
+ end
67
96
  end
data/spec/spec_helper.rb CHANGED
@@ -1,4 +1,4 @@
1
- $:.unshift File.expand_path('../lib', __FILE__)
1
+ $LOAD_PATH.unshift File.expand_path('../lib', __FILE__)
2
2
 
3
3
  require 'active_support/all'
4
4
  require 'rspec'
@@ -5,7 +5,7 @@ module DatabaseMacros
5
5
  klass = Class.new(ActiveRecord::Migration)
6
6
 
7
7
  # Create a new `up` that executes the argument
8
- klass.send(:define_method, :up) { self.instance_exec(&block) }
8
+ klass.send(:define_method, :up) { instance_exec(&block) }
9
9
 
10
10
  # Create a new instance of it and execute its `up` method
11
11
  klass.new.up
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: '0.3'
4
+ version: '0.4'
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: 2015-01-16 00:00:00.000000000 Z
11
+ date: 2015-01-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -100,6 +100,34 @@ dependencies:
100
100
  - - "<"
101
101
  - !ruby/object:Gem::Version
102
102
  version: '5'
103
+ - !ruby/object:Gem::Dependency
104
+ name: phare
105
+ requirement: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - ">="
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ type: :development
111
+ prerelease: false
112
+ version_requirements: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - ">="
115
+ - !ruby/object:Gem::Version
116
+ version: '0'
117
+ - !ruby/object:Gem::Dependency
118
+ name: rubocop
119
+ requirement: !ruby/object:Gem::Requirement
120
+ requirements:
121
+ - - "~>"
122
+ - !ruby/object:Gem::Version
123
+ version: '0.28'
124
+ type: :development
125
+ prerelease: false
126
+ version_requirements: !ruby/object:Gem::Requirement
127
+ requirements:
128
+ - - "~>"
129
+ - !ruby/object:Gem::Version
130
+ version: '0.28'
103
131
  - !ruby/object:Gem::Dependency
104
132
  name: json-schema
105
133
  requirement: !ruby/object:Gem::Requirement
@@ -158,6 +186,7 @@ extra_rdoc_files: []
158
186
  files:
159
187
  - ".gitignore"
160
188
  - ".rspec"
189
+ - ".rubocop.yml"
161
190
  - ".travis.yml"
162
191
  - Gemfile
163
192
  - LICENSE.md