couchbase-orm 1.1.1 → 2.0.0

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.
Files changed (87) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/test.yml +45 -0
  3. data/.gitignore +2 -0
  4. data/.travis.yml +3 -2
  5. data/CODEOWNERS +1 -0
  6. data/Gemfile +5 -3
  7. data/README.md +237 -31
  8. data/ci/run_couchbase.sh +22 -0
  9. data/couchbase-orm.gemspec +26 -20
  10. data/lib/couchbase-orm/active_record_compat.rb +92 -0
  11. data/lib/couchbase-orm/associations.rb +119 -0
  12. data/lib/couchbase-orm/base.rb +143 -166
  13. data/lib/couchbase-orm/changeable.rb +512 -0
  14. data/lib/couchbase-orm/connection.rb +28 -8
  15. data/lib/couchbase-orm/encrypt.rb +48 -0
  16. data/lib/couchbase-orm/error.rb +17 -2
  17. data/lib/couchbase-orm/inspectable.rb +37 -0
  18. data/lib/couchbase-orm/json_schema/json_validation_error.rb +13 -0
  19. data/lib/couchbase-orm/json_schema/loader.rb +47 -0
  20. data/lib/couchbase-orm/json_schema/validation.rb +18 -0
  21. data/lib/couchbase-orm/json_schema/validator.rb +45 -0
  22. data/lib/couchbase-orm/json_schema.rb +9 -0
  23. data/lib/couchbase-orm/json_transcoder.rb +27 -0
  24. data/lib/couchbase-orm/locale/en.yml +5 -0
  25. data/lib/couchbase-orm/n1ql.rb +133 -0
  26. data/lib/couchbase-orm/persistence.rb +61 -52
  27. data/lib/couchbase-orm/proxies/bucket_proxy.rb +36 -0
  28. data/lib/couchbase-orm/proxies/collection_proxy.rb +52 -0
  29. data/lib/couchbase-orm/proxies/n1ql_proxy.rb +40 -0
  30. data/lib/couchbase-orm/proxies/results_proxy.rb +23 -0
  31. data/lib/couchbase-orm/railtie.rb +6 -17
  32. data/lib/couchbase-orm/relation.rb +249 -0
  33. data/lib/couchbase-orm/strict_loading.rb +21 -0
  34. data/lib/couchbase-orm/timestamps/created.rb +20 -0
  35. data/lib/couchbase-orm/timestamps/updated.rb +21 -0
  36. data/lib/couchbase-orm/timestamps.rb +15 -0
  37. data/lib/couchbase-orm/types/array.rb +32 -0
  38. data/lib/couchbase-orm/types/date.rb +9 -0
  39. data/lib/couchbase-orm/types/date_time.rb +14 -0
  40. data/lib/couchbase-orm/types/encrypted.rb +17 -0
  41. data/lib/couchbase-orm/types/nested.rb +43 -0
  42. data/lib/couchbase-orm/types/timestamp.rb +18 -0
  43. data/lib/couchbase-orm/types.rb +20 -0
  44. data/lib/couchbase-orm/utilities/enum.rb +13 -1
  45. data/lib/couchbase-orm/utilities/has_many.rb +72 -36
  46. data/lib/couchbase-orm/utilities/ignored_properties.rb +15 -0
  47. data/lib/couchbase-orm/utilities/index.rb +18 -20
  48. data/lib/couchbase-orm/utilities/properties_always_exists_in_document.rb +16 -0
  49. data/lib/couchbase-orm/utilities/query_helper.rb +148 -0
  50. data/lib/couchbase-orm/utils.rb +25 -0
  51. data/lib/couchbase-orm/version.rb +1 -1
  52. data/lib/couchbase-orm/views.rb +38 -41
  53. data/lib/couchbase-orm.rb +44 -9
  54. data/lib/ext/query_n1ql.rb +124 -0
  55. data/lib/rails/generators/couchbase_orm/config/templates/couchbase.yml +3 -2
  56. data/spec/associations_spec.rb +219 -50
  57. data/spec/base_spec.rb +296 -14
  58. data/spec/collection_proxy_spec.rb +29 -0
  59. data/spec/connection_spec.rb +27 -0
  60. data/spec/couchbase-orm/active_record_compat_spec.rb +24 -0
  61. data/spec/couchbase-orm/changeable_spec.rb +16 -0
  62. data/spec/couchbase-orm/json_schema/validation_spec.rb +23 -0
  63. data/spec/couchbase-orm/json_schema/validator_spec.rb +13 -0
  64. data/spec/couchbase-orm/timestamps_spec.rb +85 -0
  65. data/spec/couchbase-orm/timestamps_spec_models.rb +36 -0
  66. data/spec/empty-json-schema/.gitkeep +0 -0
  67. data/spec/enum_spec.rb +34 -0
  68. data/spec/has_many_spec.rb +101 -54
  69. data/spec/index_spec.rb +13 -9
  70. data/spec/json-schema/JsonSchemaBaseTest.json +19 -0
  71. data/spec/json-schema/entity_snakecase.json +20 -0
  72. data/spec/json-schema/loader_spec.rb +42 -0
  73. data/spec/json-schema/specific_path.json +20 -0
  74. data/spec/json_schema_spec.rb +178 -0
  75. data/spec/n1ql_spec.rb +193 -0
  76. data/spec/persistence_spec.rb +49 -9
  77. data/spec/relation_nested_spec.rb +88 -0
  78. data/spec/relation_spec.rb +430 -0
  79. data/spec/support.rb +16 -8
  80. data/spec/type_array_spec.rb +52 -0
  81. data/spec/type_encrypted_spec.rb +114 -0
  82. data/spec/type_nested_spec.rb +191 -0
  83. data/spec/type_spec.rb +317 -0
  84. data/spec/utilities/ignored_properties_spec.rb +20 -0
  85. data/spec/utilities/properties_always_exists_in_document_spec.rb +24 -0
  86. data/spec/views_spec.rb +32 -11
  87. metadata +192 -29
@@ -2,81 +2,128 @@
2
2
 
3
3
  require File.expand_path("../support", __FILE__)
4
4
 
5
+ shared_examples "has_many example" do |parameter|
6
+ before :all do
7
+ @context = parameter[:context].to_s
8
+ @rating_test_class = Kernel.const_get("Rating#{@context.camelize}Test".classify)
9
+ @object_test_class = Kernel.const_get("Object#{@context.camelize}Test".classify)
10
+ @object_rating_test_class = Kernel.const_get("ObjectRating#{@context.camelize}Test".classify)
11
+
12
+ @rating_test_class.ensure_design_document!
13
+ @object_test_class.ensure_design_document!
14
+ @object_rating_test_class.ensure_design_document!
15
+
16
+ @rating_test_class.delete_all
17
+ @object_test_class.delete_all
18
+ @object_rating_test_class.delete_all
19
+ end
5
20
 
6
- class ObjectRatingTest < CouchbaseOrm::Base
7
- join :object_test, :rating_test
8
- view :all
9
- end
21
+ after :each do
22
+ @rating_test_class.delete_all
23
+ @object_test_class.delete_all
24
+ @object_rating_test_class.delete_all
25
+ end
10
26
 
11
- class RatingTest < CouchbaseOrm::Base
12
- enum rating: [:awesome, :good, :okay, :bad], default: :okay
13
- belongs_to :object_test
27
+ it "should return matching results" do
28
+ first = @object_test_class.create! name: :bob
29
+ second = @object_test_class.create! name: :jane
14
30
 
15
- has_many :object_tests, through: :object_rating_test
16
- view :all
17
- end
31
+ rate = @rating_test_class.create! rating: :awesome, "object_#{@context}_test": first
32
+ @rating_test_class.create! rating: :bad, "object_#{@context}_test": second
33
+ @rating_test_class.create! rating: :good, "object_#{@context}_test": first
18
34
 
19
- class ObjectTest < CouchbaseOrm::Base
20
- attribute :name, type: String
21
- has_many :rating_tests, dependent: :destroy
35
+ expect(rate.try("object_#{@context}_test_id")).to eq(first.id)
36
+ expect(@rating_test_class.respond_to?(:"find_by_object_#{@context}_test_id")).to be(true)
37
+ expect(first.respond_to?(:"rating_#{@context}_tests")).to be(true)
22
38
 
23
- view :all
24
- end
39
+ docs = first.try(:"rating_#{@context}_tests").collect(&:rating)
25
40
 
41
+ expect(docs).to match_array([1, 2])
26
42
 
27
- describe CouchbaseOrm::HasMany do
28
- before :all do
29
- RatingTest.ensure_design_document!
30
- ObjectTest.ensure_design_document!
31
- ObjectRatingTest.ensure_design_document!
43
+ first.destroy
44
+ expect { @rating_test_class.find rate.id }.to raise_error(Couchbase::Error::DocumentNotFound)
45
+ expect(@rating_test_class.send(:"#{@context}_all").count).to be(1)
32
46
  end
33
47
 
34
- after :each do
35
- ObjectTest.all.stream { |ob| ob.delete }
36
- RatingTest.all.stream { |ob| ob.delete }
37
- ObjectRatingTest.all.stream { |ob| ob.delete }
48
+ it "should work through a join model" do
49
+ first = @object_test_class.create! name: :bob
50
+ second = @object_test_class.create! name: :jane
51
+
52
+ rate1 = @rating_test_class.create! rating: :awesome, "object_#{@context}_test": first
53
+ _rate2 = @rating_test_class.create! rating: :bad, "object_#{@context}_test": second
54
+ _rate3 = @rating_test_class.create! rating: :good, "object_#{@context}_test": first
55
+
56
+ ort = @object_rating_test_class.create! "object_#{@context}_test": first, "rating_#{@context}_test": rate1
57
+ @object_rating_test_class.create! "object_#{@context}_test": second, "rating_#{@context}_test": rate1
58
+
59
+ expect(ort.try(:"rating_#{@context}_test_id".to_sym)).to eq(rate1.id)
60
+ expect(rate1.respond_to?(:"object_#{@context}_tests")).to be(true)
61
+ docs = rate1.try(:"object_#{@context}_tests").collect(&:name)
62
+
63
+ expect(docs).to match_array(['bob', 'jane'])
38
64
  end
39
65
 
40
- it "should return matching results" do
41
- first = ObjectTest.create! name: :bob
42
- second = ObjectTest.create! name: :jane
66
+ it "should work with new objects not yet saved" do
67
+ existing_object = @object_test_class.create! name: :bob
68
+ expect(existing_object.send(:"rating_#{@context}_tests")).to be_empty
43
69
 
44
- rate = RatingTest.create! rating: :awesome, object_test: first
45
- RatingTest.create! rating: :bad, object_test: second
46
- RatingTest.create! rating: :good, object_test: first
70
+ @rating_test_class.create! rating: :good, "object_#{@context}_test": existing_object
71
+
72
+ new_object = @object_test_class.new name: :jane
73
+ expect(new_object.send(:"rating_#{@context}_tests")).to be_empty
74
+ end
47
75
 
48
- expect(rate.object_test_id).to eq(first.id)
49
- expect(RatingTest.respond_to?(:find_by_object_test_id)).to be(true)
50
- expect(first.respond_to?(:rating_tests)).to be(true)
76
+ end
51
77
 
52
- docs = first.rating_tests.collect { |ob|
53
- ob.rating
54
- }
78
+ describe CouchbaseOrm::HasMany do
79
+ context 'with view' do
80
+ class ObjectRatingViewTest < CouchbaseOrm::Base
81
+ join :object_view_test, :rating_view_test
82
+ view :view_all
83
+ end
55
84
 
56
- expect(docs).to eq([1, 2])
85
+ class RatingViewTest < CouchbaseOrm::Base
86
+ enum rating: [:awesome, :good, :okay, :bad], default: :okay
87
+ belongs_to :object_view_test
57
88
 
58
- first.destroy
59
- expect { RatingTest.find rate.id }.to raise_error(::Libcouchbase::Error::KeyNotFound)
60
- expect(RatingTest.all.count).to be(1)
89
+ has_many :object_view_tests, through: :object_rating_view_test
90
+ view :view_all
91
+ end
92
+
93
+ class ObjectViewTest < CouchbaseOrm::Base
94
+ attribute :name, type: String
95
+ has_many :rating_view_tests, dependent: :destroy
96
+
97
+ view :view_all
98
+ end
99
+
100
+ include_examples("has_many example", context: :view)
61
101
  end
62
102
 
63
- it "should work through a join model" do
64
- first = ObjectTest.create! name: :bob
65
- second = ObjectTest.create! name: :jane
103
+ context 'with n1ql' do
104
+ class ObjectRatingN1qlTest < CouchbaseOrm::Base
105
+ join :object_n1ql_test, :rating_n1ql_test
106
+
107
+ n1ql :n1ql_all
108
+ end
109
+
110
+ class RatingN1qlTest < CouchbaseOrm::Base
111
+ enum rating: [:awesome, :good, :okay, :bad], default: :okay
112
+ belongs_to :object_n1ql_test
113
+
114
+ has_many :object_n1ql_tests, through: :object_rating_n1ql_test, type: :n1ql
115
+
116
+ n1ql :n1ql_all
117
+ end
66
118
 
67
- rate1 = RatingTest.create! rating: :awesome, object_test: first
68
- rate2 = RatingTest.create! rating: :bad, object_test: second
69
- rate3 = RatingTest.create! rating: :good, object_test: first
119
+ class ObjectN1qlTest < CouchbaseOrm::Base
120
+ attribute :name, type: String
70
121
 
71
- ort = ObjectRatingTest.create! object_test: first, rating_test: rate1
72
- ObjectRatingTest.create! object_test: second, rating_test: rate1
122
+ has_many :rating_n1ql_tests, dependent: :destroy, type: :n1ql
73
123
 
74
- expect(ort.rating_test_id).to eq(rate1.id)
75
- expect(rate1.respond_to?(:object_tests)).to be(true)
76
- docs = rate1.object_tests.collect { |ob|
77
- ob.name
78
- }
124
+ n1ql :n1ql_all
125
+ end
79
126
 
80
- expect(docs).to eq(['bob', 'jane'])
127
+ include_examples("has_many example", context: :n1ql)
81
128
  end
82
129
  end
data/spec/index_spec.rb CHANGED
@@ -16,15 +16,15 @@ class NoUniqueIndexTest < CouchbaseOrm::Base
16
16
  index :email, presence: false
17
17
  end
18
18
 
19
- class EnumTest < CouchbaseOrm::Base
19
+ class IndexEnumTest < CouchbaseOrm::Base
20
20
  enum visibility: [:group, :authority, :public], default: :authority
21
+ enum color: [:red, :green, :blue]
21
22
  end
22
23
 
23
24
 
24
25
  describe CouchbaseOrm::Index do
25
26
  after :each do
26
- IndexTest.bucket.delete('index_testemail-joe@aca.com')
27
- IndexTest.bucket.delete('index_testemail-')
27
+ IndexTest.all.map(&:destroy)
28
28
  end
29
29
 
30
30
  it "should prevent models being created if they should have unique keys" do
@@ -69,7 +69,7 @@ describe CouchbaseOrm::Index do
69
69
 
70
70
  it "should work with nil values" do
71
71
  joe = IndexTest.create!
72
- expect(IndexTest.find_by_email(nil)).to eq(nil)
72
+ expect(IndexTest.find_by_email(nil)).to eq(joe)
73
73
 
74
74
  joe.email = 'joe@aca.com'
75
75
  joe.save!
@@ -78,31 +78,35 @@ describe CouchbaseOrm::Index do
78
78
  joe.email = nil
79
79
  joe.save!
80
80
  expect(IndexTest.find_by_email('joe@aca.com')).to eq(nil)
81
- expect(IndexTest.find_by_email(nil)).to eq(nil)
81
+ expect(IndexTest.find_by_email(nil)).to eq(joe)
82
82
 
83
83
  joe.destroy
84
84
  end
85
85
 
86
86
  it "should work with enumerators" do
87
87
  # Test symbol
88
- enum = EnumTest.create!(visibility: :public)
88
+ enum = IndexEnumTest.create!(visibility: :public)
89
89
  expect(enum.visibility).to eq(3)
90
90
  enum.destroy
91
91
 
92
92
  # Test number
93
- enum = EnumTest.create!(visibility: 2)
93
+ enum = IndexEnumTest.create!(visibility: 2)
94
94
  expect(enum.visibility).to eq(2)
95
95
  enum.destroy
96
96
 
97
97
  # Test default
98
- enum = EnumTest.create!
98
+ enum = IndexEnumTest.create!
99
99
  expect(enum.visibility).to eq(2)
100
100
  enum.destroy
101
+
102
+ # Test default default
103
+ enum = IndexEnumTest.create!
104
+ expect(enum.color).to eq(1)
101
105
  end
102
106
 
103
107
  it "should not overwrite index's that do not belong to the current model" do
104
108
  joe = NoUniqueIndexTest.create!
105
- expect(NoUniqueIndexTest.find_by_email(nil)).to eq(nil)
109
+ expect(NoUniqueIndexTest.find_by_email(nil)).to eq(joe)
106
110
 
107
111
  joe.email = 'joe@aca.com'
108
112
  joe.save!
@@ -0,0 +1,19 @@
1
+ {
2
+ "type": "object",
3
+ "required": [
4
+ "name"
5
+ ],
6
+ "properties": {
7
+ "id": {
8
+ "type": "string"
9
+ },
10
+ "numb": {
11
+ "type": "integer",
12
+ "format": "uint32",
13
+ "minimum": 3.0
14
+ },
15
+ "name": {
16
+ "type": "string"
17
+ }
18
+ }
19
+ }
@@ -0,0 +1,20 @@
1
+ {
2
+ "type": "object",
3
+ "required": [
4
+ "value"
5
+ ],
6
+ "properties": {
7
+ "value": {
8
+ "$ref": "#/definitions/ValueType"
9
+ }
10
+ },
11
+ "definitions": {
12
+ "ValueType": {
13
+ "type": "string",
14
+ "enum": [
15
+ "value_one",
16
+ "value_two"
17
+ ]
18
+ }
19
+ }
20
+ }
@@ -0,0 +1,42 @@
1
+ require File.expand_path('../../support', __FILE__)
2
+ require 'couchbase-orm/json_schema/loader'
3
+
4
+ RSpec.describe CouchbaseOrm::JsonSchema::Loader do
5
+ let(:loader) { described_class.send(:new, "#{Dir.pwd}/spec/json-schema") }
6
+
7
+ describe '#extract_type' do
8
+ it 'returns the type from the entity' do
9
+ entity = { type: 'entity_snakecase' }
10
+ expect(loader.extract_type(entity)).to eq('entity_snakecase')
11
+
12
+ expect(loader.get_json_schema!(entity)).not_to be_nil
13
+ end
14
+ end
15
+
16
+ describe '#get_json_schema' do
17
+ context 'when schemas are present and document type exists' do
18
+ let(:schemas) { { 'user' => { 'properties' => { 'name' => { 'type' => 'string' } } } } }
19
+
20
+ before do
21
+ allow(loader).to receive(:schemas).and_return(schemas)
22
+ end
23
+
24
+ it 'returns the schema for the given document type' do
25
+ entity = { type: 'user' }
26
+ expect(loader.get_json_schema!(entity)).to eq(schemas['user'])
27
+ end
28
+
29
+ it 'raise error if no schema found for the document type' do
30
+ entity = { type: 'post' }
31
+ expect { loader.get_json_schema!(entity) }.to raise_error(CouchbaseOrm::JsonSchema::Loader::Error, /Schema not found for post in .*\/json-schema/)
32
+ end
33
+ end
34
+
35
+ context 'when schemas are not present or document type is missing' do
36
+ it 'returns nil' do
37
+ entity = { type: 'user' }
38
+ expect { loader.get_json_schema!(entity) }.to raise_error(CouchbaseOrm::JsonSchema::Loader::Error, /Schema not found for user in .*\/json-schema/)
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,20 @@
1
+ {
2
+ "type": "object",
3
+ "required": [
4
+ "foo"
5
+ ],
6
+ "properties": {
7
+ "foo": {
8
+ "$ref": "#/definitions/ValueType"
9
+ }
10
+ },
11
+ "definitions": {
12
+ "ValueType": {
13
+ "type": "string",
14
+ "enum": [
15
+ "foo_one",
16
+ "foo_two"
17
+ ]
18
+ }
19
+ }
20
+ }
@@ -0,0 +1,178 @@
1
+ # frozen_string_literal: true, encoding: ASCII-8BIT
2
+
3
+ require File.expand_path("../support", __FILE__)
4
+
5
+ class JsonSchemaBaseTest < CouchbaseOrm::Base
6
+ attribute :name, :string
7
+ attribute :numb, :integer
8
+
9
+ design_document('JsonSchemaBaseTest')
10
+ validate_json_schema
11
+ end
12
+
13
+ class UnknownTest < CouchbaseOrm::Base
14
+ attribute :test, :boolean
15
+ validate_json_schema
16
+ end
17
+
18
+ class EntitySnakecase < CouchbaseOrm::Base
19
+ attribute :value, :string
20
+ validate_json_schema
21
+ end
22
+
23
+ describe CouchbaseOrm::JsonSchema::Loader do
24
+
25
+ after(:each) do
26
+ reset_schemas
27
+ end
28
+
29
+ context "with validation enabled on model" do
30
+
31
+ it "With no existing dir " do
32
+ load_schemas("../dontexist")
33
+ expect { CouchbaseOrm::JsonSchema::Loader.instance.get_json_schema!({ :type => "Unknown" }) }.to raise_error CouchbaseOrm::JsonSchema::Loader::Error, /Schema not found for Unknown in .*\/dontexist/
34
+ end
35
+
36
+ it "Without existing json " do
37
+ load_schemas("../empty-json-schema")
38
+ expect { CouchbaseOrm::JsonSchema::Loader.instance.get_json_schema!({ :type => "Unknown" }) }.to raise_error CouchbaseOrm::JsonSchema::Loader::Error, /Schema not found for Unknown in .*\/empty-json-schema/
39
+ end
40
+
41
+ it "with schema " do
42
+ load_schemas("../json-schema")
43
+ expect(CouchbaseOrm::JsonSchema::Loader.instance.get_json_schema!({ :type => "JsonSchemaBaseTest" })).to include('"name"')
44
+ expect { CouchbaseOrm::JsonSchema::Loader.instance.get_json_schema!({ :type => "Unknown" }) }.to raise_error CouchbaseOrm::JsonSchema::Loader::Error, /Schema not found for Unknown in .*\/json-schema/
45
+ end
46
+ end
47
+
48
+ describe CouchbaseOrm::JsonSchema::Validator do
49
+ after(:each) do
50
+ reset_schemas
51
+ end
52
+
53
+ it "creation ok" do
54
+ load_schemas("../json-schema")
55
+ base = EntitySnakecase.create!(value: "value_one")
56
+ base.delete
57
+ end
58
+
59
+ it "creation ko" do
60
+ load_schemas("../json-schema")
61
+ expect { EntitySnakecase.create!(value: "value_1") }.to raise_error CouchbaseOrm::JsonSchema::JsonValidationError
62
+ end
63
+
64
+ it "update ok" do
65
+ load_schemas("../json-schema")
66
+ base = EntitySnakecase.create!(value: "value_one")
67
+ base.value = "value_two"
68
+ base.save
69
+ base.delete
70
+ end
71
+
72
+ it "update ko" do
73
+ load_schemas("../json-schema")
74
+ base = EntitySnakecase.create!(value: "value_one")
75
+ base.value = "value_2"
76
+ expect { base.save }.to raise_error CouchbaseOrm::JsonSchema::JsonValidationError
77
+ base.delete
78
+ end
79
+
80
+ it "creation ok with design_document" do
81
+ load_schemas("../json-schema")
82
+ base = JsonSchemaBaseTest.create!(name: "dsdsd", numb: 3)
83
+ base.delete
84
+ end
85
+
86
+ it "creation ko with design_document" do
87
+ load_schemas("../json-schema")
88
+ expect { JsonSchemaBaseTest.create!(name: "dsdsd", numb: 2) }.to raise_error CouchbaseOrm::JsonSchema::JsonValidationError
89
+ end
90
+
91
+ it "update ok with design_document" do
92
+ load_schemas("../json-schema")
93
+ base = JsonSchemaBaseTest.create!(name: "dsdsd", numb: 3)
94
+ base.numb = 4
95
+ base.save
96
+ base.delete
97
+ end
98
+
99
+ it "update ok with design_document" do
100
+ load_schemas("../json-schema")
101
+ base = JsonSchemaBaseTest.create!(name: "dsdsd", numb: 3)
102
+ base.numb = 2
103
+ expect { base.save }.to raise_error CouchbaseOrm::JsonSchema::JsonValidationError
104
+ base.delete
105
+ end
106
+
107
+ it 'prevent saving with entity not define in schema files and raise' do
108
+ load_schemas("../json-schema")
109
+ expect { UnknownTest.create!(test: true) }.to raise_error CouchbaseOrm::JsonSchema::Loader::Error, /Schema not found for unknown_test in .*\/json-schema/
110
+ end
111
+
112
+ it 'prevent updating with entity not define in schema files and raise' do
113
+ load_schemas("../json-schema")
114
+ base = JsonSchemaBaseTest.create!(name: 'Juju', numb: 3)
115
+ reset_schemas
116
+ base.name = 'Pierre'
117
+ expect { base.save }.to raise_error CouchbaseOrm::JsonSchema::Loader::Error, "Schema not found for JsonSchemaBaseTest in db/cborm_schemas/JsonSchemaBaseTest.json"
118
+ base.delete
119
+ end
120
+ end
121
+
122
+ context "with validation disabled on model" do
123
+ let!(:original_config) { EntitySnakecase.instance_variable_get(:@json_validation_config) }
124
+ before do
125
+ EntitySnakecase.instance_variable_set(:@json_validation_config, {enabled: false})
126
+ end
127
+ after do
128
+ EntitySnakecase.instance_variable_set(:@json_validation_config, original_config)
129
+ end
130
+ it "does not validate schema (even if scehma exists and is not valid)" do
131
+ load_schemas("../json-schema")
132
+ base = EntitySnakecase.create!(value: "value_one")
133
+ base.value = "value_2"
134
+ expect { base.save }.not_to raise_error CouchbaseOrm::JsonSchema::JsonValidationError
135
+ base.delete
136
+ end
137
+
138
+ end
139
+
140
+ context "with logger mode on model" do
141
+ before do
142
+ EntitySnakecase.instance_variable_set(:@json_validation_config, {enabled: true, mode: :logger})
143
+ end
144
+ it "does not raise error but log it" do
145
+ load_schemas("../json-schema")
146
+ base = EntitySnakecase.create!(value: "value_one")
147
+ base.value = "value_2"
148
+ expect(CouchbaseOrm.logger).to receive(:error)
149
+ base.save
150
+ base.delete
151
+ end
152
+ end
153
+
154
+ context "when schema_path is set on model" do
155
+ let!(:original_config) { EntitySnakecase.instance_variable_get(:@json_validation_config) }
156
+ before do
157
+ EntitySnakecase.instance_variable_set(:@json_validation_config, {enabled: true, mode: :strict, schema_path: 'spec/json-schema/specific_path.json'})
158
+ end
159
+ after do
160
+ EntitySnakecase.instance_variable_set(:@json_validation_config, original_config)
161
+ end
162
+ it "loads schema from the specified path" do
163
+ expect { EntitySnakecase.create!(value: "value_one") }.to raise_error CouchbaseOrm::JsonSchema::JsonValidationError, /did not contain a required property of 'foo' in schema/
164
+ end
165
+ end
166
+ end
167
+
168
+
169
+ # TODO : extract following helpers methods elsewhere
170
+
171
+ def load_schemas(file_relative_path)
172
+ CouchbaseOrm::JsonSchema::Loader.instance.send(:instance_variable_set, :@schemas_directory, File.expand_path(file_relative_path, __FILE__))
173
+ end
174
+
175
+ def reset_schemas
176
+ CouchbaseOrm::JsonSchema::Loader.instance.send(:instance_variable_set, :@schemas_directory, CouchbaseOrm::JsonSchema::Loader::JSON_SCHEMAS_PATH)
177
+ CouchbaseOrm::JsonSchema::Loader.instance.instance_variable_get(:@schemas).clear
178
+ end