mongoid-multitenancy 2.0.3 → 2.0.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 57b6a36dd90e26ab59298efdd32bfeb5b92a1bfd
4
- data.tar.gz: da726e93d69c677784b0bb5213d21bda3a77af3b
2
+ SHA256:
3
+ metadata.gz: 485b7b5927867bd3f2e3d33aa0705a0f78422a81cba9b5f207b7c71ba56fda65
4
+ data.tar.gz: 07c63615e55a7a66d7776bf61b8fd741dd15105bfb14404742242dfe36cc0387
5
5
  SHA512:
6
- metadata.gz: b11cda4238d5ef849b59ce910c70136692e04680c764159c128cf38eea5fd89851e8d9d728a3773edbf27ed0013d9fbc2e2777babe2b977c4bcab160198ecca2
7
- data.tar.gz: bf624d27f91d4ac108f811445eaa9fbbb4837e88427cc4a5eb7d810c9adbb19f6310f7a94ac84592560f371ad9ed666999498a7395cc562f495d845be724880e
6
+ metadata.gz: 406b1104c97d9faa39822f114bb4c4b0687e2aedcf0f307e5dc2d90a96ef11a89509988a585f79030aec5ec2948ead959a351d558cc933152f55344b6ee3c96f
7
+ data.tar.gz: e46f79ec9b5dbe8adef7f3f5da17e6eb34397f600679e5c2f8c140b1c6911a88712b919b3c3e7a4fc9938f63731354c268e97345261441384ac821f83d2e3ebd
data/.travis.yml CHANGED
@@ -6,6 +6,8 @@ rvm:
6
6
  gemfile:
7
7
  - gemfiles/Gemfile.mongoid-6
8
8
  - gemfiles/Gemfile.mongoid-7
9
+ - gemfiles/Gemfile.mongoid-8
10
+ - gemfiles/Gemfile.mongoid-9
9
11
  - Gemfile
10
12
  services:
11
13
  - mongodb
data/CHANGELOG.md CHANGED
@@ -4,6 +4,16 @@ All notable changes to this project will be documented in this file.
4
4
  The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
5
5
  and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
6
6
 
7
+ ## [2.0.5] - 2024-09-20
8
+ ### Fixed
9
+
10
+ * Fix uniqueness validator when used with conditions
11
+
12
+ ## [2.0.4] - 2024-06-17
13
+ ### Fixed
14
+
15
+ * Full Support of mongoid 8 & 9
16
+
7
17
  ## [2.0.3] - 2020-06-25
8
18
  ### Fixed
9
19
 
data/Gemfile CHANGED
@@ -3,7 +3,7 @@ source 'https://rubygems.org'
3
3
  gem 'rake'
4
4
 
5
5
  group :test do
6
- gem 'database_cleaner'
6
+ gem 'database_cleaner-mongoid'
7
7
  gem 'coveralls', require: false
8
8
  gem 'rspec', '~> 3.1'
9
9
  gem 'yard'
data/README.md CHANGED
@@ -15,7 +15,7 @@ In addition, mongoid-multitenancy:
15
15
  Compatibility
16
16
  ===============
17
17
 
18
- mongoid-multitenancy 2.0 is compatible with mongoid 6/7. For mongoid 4/5 compatiblity, use mongoid-multitenancy 1.2.
18
+ mongoid-multitenancy 2 is compatible with mongoid 6/7/8/9. For mongoid 4/5 compatiblity, use mongoid-multitenancy 1.2.
19
19
 
20
20
  Installation
21
21
  ===============
@@ -226,16 +226,32 @@ class Article
226
226
  end
227
227
  ```
228
228
 
229
+ TenantUniqueness validator also allow to specify additional `conditions` to limit the uniqueness of the constraint.
230
+
231
+ ```ruby
232
+ class Article
233
+ include Mongoid::Document
234
+ include Mongoid::Multitenancy::Document
235
+
236
+ tenant :tenant, optional: true
237
+
238
+ field :title
239
+ field :slug
240
+
241
+ validates_tenant_uniqueness_of :slug, exclude_shared: true, conditions: -> { ne(title: nil) }
242
+ end
243
+ ```
244
+
229
245
  Mongoid indexes
230
246
  -------------------
231
247
 
232
- mongoid-multitenancy automatically adds the tenant foreign key in all your mongoid indexes to avoid to redefine all your validators. If you prefer to define manually the indexes, you can use the option `full_indexes: false`.
248
+ mongoid-multitenancy automatically adds the tenant foreign key in all your mongoid indexes to avoid to redefine all your validators. If you prefer to define the indexes manually, you can use the option `full_indexes: false` on the tenant or `full_index: true/false` on the indexes.
233
249
 
234
250
  To create a single index on the tenant field, you can use the option `index: true` like any `belongs_to` declaration (false by default)
235
251
 
236
- On the example below, only one indexe will be created:
252
+ On the example below, only one index will be created:
237
253
 
238
- * { 'title_id' => 1, 'tenant_id' => 1 }
254
+ * { 'tenant_id' => 1, 'title' => 1 }
239
255
 
240
256
  ```ruby
241
257
  class Article
@@ -250,10 +266,11 @@ class Article
250
266
  end
251
267
  ```
252
268
 
253
- On the example below, 2 indexes will be created:
269
+ On the example below, 3 indexes will be created:
254
270
 
255
271
  * { 'tenant_id' => 1 }
256
- * { 'title_id' => 1 }
272
+ * { 'tenant_id' => 1, 'title' => 1 }
273
+ * { 'name' => 1 }
257
274
 
258
275
  ```ruby
259
276
  class Article
@@ -263,8 +280,10 @@ class Article
263
280
  tenant :tenant, index: true
264
281
 
265
282
  field :title
283
+ field :name
266
284
 
267
285
  index({ :title => 1 })
286
+ index({ :name => 1 }, { full_index: false })
268
287
  end
269
288
  ```
270
289
 
@@ -5,7 +5,7 @@ gem 'mongoid', '~> 6.0'
5
5
  gem 'rake'
6
6
 
7
7
  group :test do
8
- gem 'database_cleaner'
8
+ gem 'database_cleaner-mongoid'
9
9
  gem 'coveralls', require: false
10
10
  gem 'rspec', '~> 3.1'
11
11
  gem 'yard'
@@ -5,7 +5,7 @@ gem 'mongoid', '~> 7.0'
5
5
  gem 'rake'
6
6
 
7
7
  group :test do
8
- gem 'database_cleaner'
8
+ gem 'database_cleaner-mongoid'
9
9
  gem 'coveralls', require: false
10
10
  gem 'rspec', '~> 3.1'
11
11
  gem 'yard'
@@ -0,0 +1,14 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'mongoid', '~> 8.0'
4
+
5
+ gem 'rake'
6
+
7
+ group :test do
8
+ gem 'database_cleaner-mongoid'
9
+ gem 'coveralls', require: false
10
+ gem 'rspec', '~> 3.1'
11
+ gem 'yard'
12
+ gem 'mongoid-rspec', git: 'https://github.com/mongoid-rspec/mongoid-rspec.git'
13
+ gem 'rubocop', require: false
14
+ end
@@ -0,0 +1,14 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'mongoid', '~> 9.0'
4
+
5
+ gem 'rake'
6
+
7
+ group :test do
8
+ gem 'database_cleaner-mongoid'
9
+ gem 'coveralls', require: false
10
+ gem 'rspec', '~> 3.1'
11
+ gem 'yard'
12
+ gem 'mongoid-rspec', git: 'https://github.com/mongoid-rspec/mongoid-rspec.git'
13
+ gem 'rubocop', require: false
14
+ end
@@ -87,11 +87,13 @@ module Mongoid
87
87
 
88
88
  # Redefine 'index' to include the tenant field in first position
89
89
  def index(spec, options = nil)
90
- if tenant_options[:full_indexes]
90
+ super_options = (options || {}).dup
91
+ full_index = super_options.delete(:full_index)
92
+ if full_index.nil? ? tenant_options[:full_indexes] : full_index
91
93
  spec = { tenant_field => 1 }.merge(spec)
92
94
  end
93
95
 
94
- super(spec, options)
96
+ super(spec, super_options)
95
97
  end
96
98
 
97
99
  # Redefine 'delete_all' to take in account the default scope
@@ -37,7 +37,11 @@ module Mongoid
37
37
 
38
38
  # <<Add the tenant Criteria>>
39
39
  criteria = with_tenant_criterion(criteria, klass, document)
40
- criteria = criteria.merge(options[:conditions].call) if options[:conditions]
40
+ # Add additional conditions
41
+ if options[:conditions]
42
+ conditions = klass.unscoped { options[:conditions].call }
43
+ criteria = criteria.merge(conditions)
44
+ end
41
45
 
42
46
  if criteria.read(mode: :primary).exists?
43
47
  add_error(document, attribute, value)
@@ -1,6 +1,6 @@
1
1
  module Mongoid
2
2
  module Multitenancy
3
3
  # Version
4
- VERSION = '2.0.3'.freeze
4
+ VERSION = '2.0.5'.freeze
5
5
  end
6
6
  end
@@ -15,5 +15,5 @@ Gem::Specification.new do |gem|
15
15
  gem.require_paths = ['lib']
16
16
  gem.version = Mongoid::Multitenancy::VERSION
17
17
 
18
- gem.add_dependency('mongoid', '>= 6', '< 8')
18
+ gem.add_dependency('mongoid', '>= 6', '< 10')
19
19
  end
@@ -0,0 +1,61 @@
1
+ require 'spec_helper'
2
+
3
+ describe ConditionalUniqueness do
4
+ let(:client) do
5
+ Account.create!(name: 'client')
6
+ end
7
+
8
+ let(:another_client) do
9
+ Account.create!(name: 'another client')
10
+ end
11
+
12
+ let(:item) do
13
+ ConditionalUniqueness.new(approved: true, slug: 'page-x')
14
+ end
15
+
16
+ it_behaves_like 'a tenantable model'
17
+
18
+ describe '#valid?' do
19
+ context 'with a tenant' do
20
+ before do
21
+ Mongoid::Multitenancy.current_tenant = client
22
+ end
23
+
24
+ it 'is valid' do
25
+ expect(item).to be_valid
26
+ end
27
+
28
+ context 'with a duplicate on the constraint' do
29
+ let(:duplicate) do
30
+ ConditionalUniqueness.new(approved: true, slug: 'page-x')
31
+ end
32
+
33
+ before do
34
+ item.save!
35
+ end
36
+
37
+ it 'is not valid' do
38
+ expect(duplicate).not_to be_valid
39
+ end
40
+
41
+ context 'with a duplicate outside the conditions' do
42
+ before do
43
+ item.update(approved: false)
44
+ end
45
+
46
+ it 'is valid' do
47
+ expect(duplicate).to be_valid
48
+ end
49
+ end
50
+
51
+ context 'with a different tenant' do
52
+ it 'is valid' do
53
+ Mongoid::Multitenancy.with_tenant(another_client) do
54
+ expect(duplicate).to be_valid
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
@@ -9,27 +9,62 @@ describe 'tenant' do
9
9
  Mongoid::Multitenancy.current_tenant = client
10
10
  end
11
11
 
12
- context 'without index: true' do
13
- it 'does not create an index' do
14
- expect(Immutable).not_to have_index_for(tenant_id: 1)
12
+ describe 'tenant full_indexes option' do
13
+ context 'without index option' do
14
+ it 'does not create an index' do
15
+ expect(IndexableWithoutIndex).not_to have_index_for(tenant_id: 1)
16
+ end
15
17
  end
16
- end
17
18
 
18
- context 'with index: true' do
19
- it 'creates an index' do
20
- expect(Indexable).to have_index_for(tenant_id: 1)
19
+ context 'with index: false' do
20
+ it 'does not create an index' do
21
+ expect(IndexableWithIndexFalse).not_to have_index_for(tenant_id: 1)
22
+ end
21
23
  end
22
- end
23
24
 
24
- context 'with full_indexes: true' do
25
- it 'add the tenant field on each index' do
26
- expect(Immutable).to have_index_for(tenant_id: 1, title: 1)
25
+ context 'with index: true' do
26
+ it 'creates an index' do
27
+ expect(IndexableWithIndexTrue).to have_index_for(tenant_id: 1)
28
+ end
27
29
  end
28
30
  end
29
31
 
30
- context 'with full_indexes: false' do
31
- it 'does not add the tenant field on each index' do
32
- expect(Indexable).not_to have_index_for(tenant_id: 1, title: 1)
32
+ describe 'index full_index option' do
33
+ context 'without tenant full_indexes option specified' do
34
+ it 'adds the tenant field on each index' do
35
+ expect(IndexableWithoutFullIndexes).to have_index_for(tenant_id: 1, title: 1)
36
+ end
37
+
38
+ it 'adds the tenant field on the index with full_index: true' do
39
+ expect(IndexableWithoutFullIndexes).to have_index_for(tenant_id: 1, name: 1)
40
+ end
41
+
42
+ it 'does not add the tenant field on the index with full_index: false' do
43
+ expect(IndexableWithoutFullIndexes).not_to have_index_for(tenant_id: 1, slug: 1)
44
+ expect(IndexableWithoutFullIndexes).to have_index_for(slug: 1)
45
+ end
46
+ end
47
+
48
+ context 'with full_indexes: true' do
49
+ it 'adds the tenant field on each index' do
50
+ expect(IndexableWithFullIndexesTrue).to have_index_for(tenant_id: 1, title: 1)
51
+ end
52
+
53
+ it 'does not add the tenant field on the index with full_index: false' do
54
+ expect(IndexableWithFullIndexesTrue).not_to have_index_for(tenant_id: 1, name: 1)
55
+ expect(IndexableWithFullIndexesTrue).to have_index_for(name: 1)
56
+ end
57
+ end
58
+
59
+ context 'with full_indexes: false' do
60
+ it 'does not add the tenant field on each index' do
61
+ expect(IndexableWithFullIndexesFalse).not_to have_index_for(tenant_id: 1, title: 1)
62
+ expect(IndexableWithFullIndexesFalse).to have_index_for(title: 1)
63
+ end
64
+
65
+ it 'does add the tenant field on the index with full_index: true' do
66
+ expect(IndexableWithFullIndexesFalse).to have_index_for(tenant_id: 1, name: 1)
67
+ end
33
68
  end
34
69
  end
35
70
  end
@@ -0,0 +1,14 @@
1
+ class ConditionalUniqueness
2
+ include Mongoid::Document
3
+ include Mongoid::Multitenancy::Document
4
+
5
+ tenant(:tenant, class_name: 'Account', optional: true)
6
+
7
+ field :slug, type: String
8
+ field :approved, type: Boolean, default: false
9
+
10
+ validates_tenant_uniqueness_of :slug, conditions: -> { where(approved: true) }
11
+ validates_presence_of :slug
12
+
13
+ index(title: 1)
14
+ end
@@ -1,10 +1,61 @@
1
- class Indexable
1
+ class IndexableWithoutIndex
2
+ include Mongoid::Document
3
+ include Mongoid::Multitenancy::Document
4
+
5
+ tenant :tenant, class_name: 'Account'
6
+ end
7
+
8
+ class IndexableWithIndexTrue
9
+ include Mongoid::Document
10
+ include Mongoid::Multitenancy::Document
11
+
12
+ tenant :tenant, class_name: 'Account', index: true
13
+ end
14
+
15
+ class IndexableWithIndexFalse
16
+ include Mongoid::Document
17
+ include Mongoid::Multitenancy::Document
18
+
19
+ tenant :tenant, class_name: 'Account', index: false
20
+ end
21
+
22
+ class IndexableWithoutFullIndexes
23
+ include Mongoid::Document
24
+ include Mongoid::Multitenancy::Document
25
+
26
+ field :title, type: String
27
+ field :name, type: String
28
+ field :slug, type: String
29
+
30
+ tenant :tenant, class_name: 'Account'
31
+
32
+ index(title: 1)
33
+ index({ name: 1 }, { full_index: true })
34
+ index({ slug: 1 }, { full_index: false })
35
+ end
36
+
37
+ class IndexableWithFullIndexesFalse
38
+ include Mongoid::Document
39
+ include Mongoid::Multitenancy::Document
40
+
41
+ field :title, type: String
42
+ field :name, type: String
43
+
44
+ tenant :tenant, class_name: 'Account', full_indexes: false
45
+
46
+ index(title: 1)
47
+ index({ name: 1 }, { full_index: true })
48
+ end
49
+
50
+ class IndexableWithFullIndexesTrue
2
51
  include Mongoid::Document
3
52
  include Mongoid::Multitenancy::Document
4
53
 
5
54
  field :title, type: String
55
+ field :name, type: String
6
56
 
7
- tenant :tenant, class_name: 'Account', index: true, full_indexes: false
57
+ tenant :tenant, class_name: 'Account', full_indexes: true
8
58
 
9
59
  index(title: 1)
60
+ index({ name: 1 }, { full_index: false })
10
61
  end
@@ -7,7 +7,7 @@ class OptionalExclude
7
7
  field :slug, type: String
8
8
  field :title, type: String
9
9
 
10
- validates_tenant_uniqueness_of :slug, exclude_shared: true
10
+ validates_tenant_uniqueness_of :slug, exclude_shared: true, conditions: -> { ne(title: nil) }
11
11
  validates_presence_of :slug
12
12
  validates_presence_of :title
13
13
 
data/spec/spec_helper.rb CHANGED
@@ -2,7 +2,7 @@ MODELS = File.join(File.dirname(__FILE__), 'models')
2
2
 
3
3
  require 'simplecov'
4
4
  require 'coveralls'
5
- require 'database_cleaner'
5
+ require 'database_cleaner-mongoid'
6
6
 
7
7
  SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[
8
8
  SimpleCov::Formatter::HTMLFormatter,
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mongoid-multitenancy
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.3
4
+ version: 2.0.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Aymeric Brisse
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-06-25 00:00:00.000000000 Z
11
+ date: 2024-09-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: mongoid
@@ -19,7 +19,7 @@ dependencies:
19
19
  version: '6'
20
20
  - - "<"
21
21
  - !ruby/object:Gem::Version
22
- version: '8'
22
+ version: '10'
23
23
  type: :runtime
24
24
  prerelease: false
25
25
  version_requirements: !ruby/object:Gem::Requirement
@@ -29,7 +29,7 @@ dependencies:
29
29
  version: '6'
30
30
  - - "<"
31
31
  - !ruby/object:Gem::Version
32
- version: '8'
32
+ version: '10'
33
33
  description: MultiTenancy with Mongoid
34
34
  email:
35
35
  - aymeric.brisse@mperfect-memory.com
@@ -47,6 +47,8 @@ files:
47
47
  - Rakefile
48
48
  - gemfiles/Gemfile.mongoid-6
49
49
  - gemfiles/Gemfile.mongoid-7
50
+ - gemfiles/Gemfile.mongoid-8
51
+ - gemfiles/Gemfile.mongoid-9
50
52
  - lib/mongoid-multitenancy.rb
51
53
  - lib/mongoid/multitenancy.rb
52
54
  - lib/mongoid/multitenancy/document.rb
@@ -54,11 +56,13 @@ files:
54
56
  - lib/mongoid/multitenancy/validators/tenant_uniqueness.rb
55
57
  - lib/mongoid/multitenancy/version.rb
56
58
  - mongoid-multitenancy.gemspec
59
+ - spec/conditional_uniqueness_spec.rb
57
60
  - spec/immutable_spec.rb
58
61
  - spec/indexable_spec.rb
59
62
  - spec/inheritance_spec.rb
60
63
  - spec/mandatory_spec.rb
61
64
  - spec/models/account.rb
65
+ - spec/models/conditional_uniqueness.rb
62
66
  - spec/models/immutable.rb
63
67
  - spec/models/indexable.rb
64
68
  - spec/models/mandatory.rb
@@ -95,17 +99,18 @@ required_rubygems_version: !ruby/object:Gem::Requirement
95
99
  - !ruby/object:Gem::Version
96
100
  version: '0'
97
101
  requirements: []
98
- rubyforge_project:
99
- rubygems_version: 2.6.14.4
102
+ rubygems_version: 3.3.27
100
103
  signing_key:
101
104
  specification_version: 4
102
105
  summary: Support of a multi-tenant database with Mongoid
103
106
  test_files:
107
+ - spec/conditional_uniqueness_spec.rb
104
108
  - spec/immutable_spec.rb
105
109
  - spec/indexable_spec.rb
106
110
  - spec/inheritance_spec.rb
107
111
  - spec/mandatory_spec.rb
108
112
  - spec/models/account.rb
113
+ - spec/models/conditional_uniqueness.rb
109
114
  - spec/models/immutable.rb
110
115
  - spec/models/indexable.rb
111
116
  - spec/models/mandatory.rb