mongoid_ability 0.0.11 → 0.1.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 (31) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +18 -13
  3. data/lib/mongoid_ability.rb +8 -2
  4. data/lib/mongoid_ability/ability.rb +32 -30
  5. data/lib/mongoid_ability/accessible_query_builder.rb +61 -41
  6. data/lib/mongoid_ability/lock.rb +16 -29
  7. data/lib/mongoid_ability/owner.rb +6 -22
  8. data/lib/mongoid_ability/resolve_default_locks.rb +15 -0
  9. data/lib/mongoid_ability/resolve_inherited_locks.rb +32 -0
  10. data/lib/mongoid_ability/resolve_locks.rb +34 -0
  11. data/lib/mongoid_ability/resolve_owner_locks.rb +25 -0
  12. data/lib/mongoid_ability/subject.rb +28 -32
  13. data/lib/mongoid_ability/version.rb +1 -1
  14. data/test/mongoid_ability/ability_role_test.rb +11 -5
  15. data/test/mongoid_ability/ability_test.rb +67 -91
  16. data/test/mongoid_ability/accessible_query_builder_test.rb +9 -5
  17. data/test/mongoid_ability/can_options_test.rb +17 -0
  18. data/test/mongoid_ability/lock_test.rb +51 -70
  19. data/test/mongoid_ability/owner_locks_test.rb +42 -0
  20. data/test/mongoid_ability/owner_test.rb +12 -39
  21. data/test/mongoid_ability/resolve_default_locks_test.rb +27 -0
  22. data/test/mongoid_ability/resolve_inherited_locks_test.rb +49 -0
  23. data/test/mongoid_ability/resolve_locks_test.rb +25 -0
  24. data/test/mongoid_ability/resolve_owner_locks_test.rb +50 -0
  25. data/test/mongoid_ability/subject_accessible_by_test.rb +135 -0
  26. data/test/mongoid_ability/subject_test.rb +20 -201
  27. data/test/support/test_classes.rb +136 -61
  28. data/test/test_helper.rb +3 -2
  29. metadata +20 -5
  30. data/lib/mongoid_ability/ability_resolver.rb +0 -42
  31. data/test/mongoid_ability/ability_resolver_test.rb +0 -78
@@ -0,0 +1,135 @@
1
+ require 'test_helper'
2
+
3
+ module MongoidAbility
4
+ describe '.accessible_by' do
5
+
6
+ let(:role_1) { MyRole.new }
7
+ let(:role_2) { MyRole.new }
8
+ let(:owner) { MyOwner.new(my_roles: [ role_1, role_2 ]) }
9
+ let(:ability) { Ability.new(owner) }
10
+
11
+ before do
12
+ MySubject.default_locks = [ MyLock.new(subject_type: MySubject, action: :read, outcome: true) ]
13
+ MySubject1.default_locks = []
14
+
15
+ @my_subject = MySubject.create!
16
+ @my_subject_1 = MySubject1.create!
17
+ end
18
+
19
+ # =====================================================================
20
+
21
+ describe 'default locks' do
22
+ describe 'when open' do
23
+ it 'returns everything' do
24
+ MySubject.accessible_by(ability, :read).to_a.must_include @my_subject
25
+ MySubject.accessible_by(ability, :read).to_a.must_include @my_subject_1
26
+ end
27
+ end
28
+
29
+ describe 'when closed' do
30
+ before do
31
+ MySubject.default_locks = [ MyLock.new(subject_type: MySubject, action: :read, outcome: false) ]
32
+ MySubject1.default_locks = []
33
+ end
34
+
35
+ it 'returns nothing' do
36
+ MySubject.accessible_by(ability, :read).to_a.wont_include @my_subject
37
+ MySubject.accessible_by(ability, :read).to_a.wont_include @my_subject_1
38
+ end
39
+ end
40
+ end
41
+
42
+ # ---------------------------------------------------------------------
43
+
44
+ describe 'subject_type lock' do
45
+ describe 'on roles' do
46
+ it 'overrides default lock' do
47
+ role_1.my_locks = [ MyLock.new(subject_type: MySubject, action: :read, outcome: false) ]
48
+ MySubject.accessible_by(ability, :read).to_a.must_be :empty?
49
+ end
50
+
51
+ it 'takes the most permissive of roles' do
52
+ role_1.my_locks = [ MyLock.new(subject_type: MySubject, action: :read, outcome: false) ]
53
+ role_2.my_locks = [ MyLock.new(subject_type: MySubject, action: :read, outcome: true) ]
54
+ MySubject.accessible_by(ability, :read).to_a.must_include @my_subject
55
+ MySubject.accessible_by(ability, :read).to_a.must_include @my_subject_1
56
+ end
57
+ end
58
+
59
+ describe 'on user' do
60
+ it 'overrides default lock' do
61
+ owner.my_locks = [ MyLock.new(subject_type: MySubject, action: :read, outcome: false) ]
62
+ MySubject.accessible_by(ability, :read).to_a.must_be :empty?
63
+ end
64
+
65
+ it 'overrides role locks' do
66
+ role_1.my_locks = [ MyLock.new(subject_type: MySubject, action: :read, outcome: false) ]
67
+ owner.my_locks = [ MyLock.new(subject_type: MySubject, action: :read, outcome: true) ]
68
+ MySubject.accessible_by(ability, :read).to_a.must_include @my_subject
69
+ MySubject.accessible_by(ability, :read).to_a.must_include @my_subject_1
70
+ end
71
+ end
72
+ end
73
+
74
+ # ---------------------------------------------------------------------
75
+
76
+ describe 'subject_id lock' do
77
+ describe 'on roles' do
78
+ it 'overrides default lock' do
79
+ role_1.my_locks = [ MyLock.new(subject: @my_subject, action: :read, outcome: false) ]
80
+ MySubject1.accessible_by(ability, :read).to_a.wont_include @my_subject
81
+ end
82
+
83
+ it 'overrides default negative lock' do
84
+ MySubject.default_locks = [ MyLock.new(subject_type: MySubject, action: :read, outcome: false) ]
85
+ role_1.my_locks = [ MyLock.new(subject: @my_subject, action: :read, outcome: true) ]
86
+ MySubject.accessible_by(ability, :read).to_a.must_include @my_subject
87
+ end
88
+
89
+ it 'overrides subject_type lock' do
90
+ role_1.my_locks = [ MyLock.new(subject_type: MySubject, action: :read, outcome: false) ]
91
+ role_2.my_locks = [ MyLock.new(subject: @my_subject, action: :read, outcome: true) ]
92
+ MySubject.accessible_by(ability, :read).to_a.must_include @my_subject
93
+ end
94
+
95
+ it 'takes the most permissive of roles' do
96
+ role_1.my_locks = [ MyLock.new(subject: @my_subject, action: :read, outcome: true) ]
97
+ role_2.my_locks = [ MyLock.new(subject: @my_subject, action: :read, outcome: false) ]
98
+ MySubject.accessible_by(ability, :read).to_a.must_include @my_subject
99
+ end
100
+
101
+ describe 'for subclasses' do
102
+ it 'overrides default negative lock' do
103
+ MySubject.default_locks = [ MyLock.new(subject_type: MySubject1, action: :read, outcome: false) ]
104
+ role_1.my_locks = [ MyLock.new(subject: @my_subject_1, action: :read, outcome: true) ]
105
+ MySubject.accessible_by(ability, :read).to_a.wont_include @my_subject
106
+ MySubject.accessible_by(ability, :read).to_a.must_include @my_subject_1
107
+ end
108
+ end
109
+ end
110
+
111
+ describe 'on user' do
112
+ it 'overrides default lock' do
113
+ owner.my_locks = [ MyLock.new(subject_type: MySubject, action: :read, outcome: false) ]
114
+ MySubject.accessible_by(ability, :read).to_a.must_be :empty?
115
+ end
116
+
117
+ it 'overrides subject_type lock' do
118
+ owner.my_locks = [
119
+ MyLock.new(subject_type: MySubject, action: :read, outcome: false),
120
+ MyLock.new(subject_type: MySubject1, action: :read, outcome: true)
121
+ ]
122
+ MySubject.accessible_by(ability, :read).to_a.wont_include @my_subject
123
+ MySubject.accessible_by(ability, :read).to_a.must_include @my_subject_1
124
+ end
125
+
126
+ it 'overrides role locks' do
127
+ role_1.my_locks = [ MyLock.new(subject_type: MySubject, action: :read, outcome: false) ]
128
+ owner.my_locks = [ MyLock.new(subject_type: MySubject, action: :read, outcome: true) ]
129
+ MySubject.accessible_by(ability, :read).to_a.must_include @my_subject
130
+ end
131
+ end
132
+ end
133
+
134
+ end
135
+ end
@@ -2,222 +2,41 @@ require 'test_helper'
2
2
 
3
3
  module MongoidAbility
4
4
  describe Subject do
5
+ describe '.default_locks' do
5
6
 
6
- def subject_type_lock subject_cls, outcome
7
- TestLock.new(subject_type: subject_cls.to_s, action: :read, outcome: outcome)
8
- end
9
-
10
- def subject_lock subject, outcome
11
- TestLock.new(subject: subject, action: :read, outcome: outcome)
12
- end
13
-
14
- # ---------------------------------------------------------------------
15
-
16
- subject { SubjectTest.new }
17
-
18
- let(:subject_single_test) { SubjectSingleTest.create! }
19
-
20
- let(:subject_test_1) { SubjectTestOne.create! }
21
- let(:subject_test_2) { SubjectTestTwo.create! }
22
-
23
- let(:role_1) { TestRole.new }
24
- let(:role_2) { TestRole.new }
25
-
26
- let(:user) { TestUser.new(roles: [role_1, role_2]) }
27
- let(:ability) { Ability.new(user) }
28
-
29
- # =====================================================================
30
-
31
- describe 'class methods' do
32
- it '.default_locks' do
33
- subject.class.must_respond_to :default_locks
34
- subject.class.default_locks.must_be_kind_of Array
35
- end
36
-
37
- it '.default_lock' do
38
- subject.class.must_respond_to :default_lock
39
- end
40
-
41
- it 'default_locks_with_inherited' do
42
- subject.class.must_respond_to :default_locks_with_inherited
43
- subject.class.default_locks_with_inherited.must_be_kind_of Array
44
- subject_test_1.class.default_locks_with_inherited.must_equal subject.class.default_locks
45
- end
46
-
47
- describe '.default_lock' do
48
- it 'sets up new Lock' do
49
- lock = subject.class.default_locks.first
50
- subject.class.default_locks.length.must_equal 1
51
- lock.subject_type.must_equal subject.class.model_name
52
- lock.subject_id.must_be_nil
53
- lock.action.must_equal :read
54
- end
55
-
56
- describe 'when trying to insert another lock for same action' do
57
- before { subject.class.default_lock :read, false }
58
- after { subject.class.default_lock :read, true }
59
-
60
- it 'does not create duplicate' do
61
- subject.class.default_locks.select{ |l| l.action == :read }.length.must_equal 1
62
- end
63
- it 'sets the new outcome' do
64
- subject.class.default_locks.select{ |l| l.action == :read }.first.outcome.must_equal false
65
- end
66
- end
67
- end
7
+ before do
8
+ MySubject.default_locks = []
9
+ MySubject1.default_locks = []
68
10
 
69
- # =====================================================================
70
-
71
- describe '.ancestors_with_default_locks' do
72
- it 'lists ancestors with default locks' do
73
- subject_test_1.class.ancestors_with_default_locks.must_equal [subject.class]
74
- end
11
+ MySubject.default_lock MyLock, :read, true
12
+ MySubject1.default_lock MyLock1, :update, false
75
13
  end
76
14
 
77
- describe '.self_and_ancestors_with_default_locks' do
78
- it 'lists self and ancestors with default locks' do
79
- subject_test_1.class.self_and_ancestors_with_default_locks.must_equal [subject_test_1.class, subject.class]
80
- end
15
+ it 'stores them' do
16
+ MySubject.default_locks.map(&:action).map(&:to_s).sort.must_equal %w(read)
17
+ MySubject1.default_locks.map(&:action).map(&:to_s).sort.must_equal %w(update)
81
18
  end
82
19
 
83
- # =====================================================================
84
-
85
- describe '.accessible_by' do
20
+ describe 'prevents conflicts' do
86
21
  before do
87
- subject_test_1
88
- subject_test_2
89
- subject_single_test
22
+ # FIXME: this permanently adjusts the default test locks – ideally do this other way, stubs etc.
23
+ MySubject.default_lock MyLock, :read, false
24
+ MySubject.default_lock MyLock1, :read, false
90
25
  end
91
26
 
92
- # ---------------------------------------------------------------------
93
-
94
- describe 'default locks' do
95
- it 'returns everything when open' do
96
- subject.class.stub(:default_locks, [ subject_type_lock(subject.class, true) ]) do
97
- subject.class.accessible_by(ability).must_include subject_test_1
98
- subject.class.accessible_by(ability).must_include subject_test_2
99
- end
100
- end
101
-
102
- describe 'single class' do
103
- it 'returns everything when open' do
104
- subject_single_test.class.stub(:default_locks, [ subject_type_lock(subject_single_test.class, true) ]) do
105
- subject_single_test.class.accessible_by(ability).must_include subject_single_test
106
- end
107
- end
108
- end
109
-
110
- it 'returns nothing when closed' do
111
- subject.class.stub(:default_locks, [ subject_type_lock(subject.class, false) ]) do
112
- subject.class.accessible_by(ability).must_be :empty?
113
- end
114
- end
115
-
116
- describe 'single class' do
117
- it 'returns nothing when closed' do
118
- subject_single_test.class.stub(:default_locks, [ subject_type_lock(subject_single_test.class, false) ]) do
119
- subject_single_test.class.accessible_by(ability).wont_include subject_single_test
120
- end
121
- end
122
- end
27
+ it 'does not allow multiple locks for same action' do
28
+ MySubject.default_locks.select{ |l| l.action == :read }.count.must_equal 1
123
29
  end
124
30
 
125
- # ---------------------------------------------------------------------
126
-
127
- describe 'subject_type lock' do
128
- describe 'on roles' do
129
- it 'overrides default lock' do
130
- role_1.test_locks = [ subject_type_lock(subject.class, false) ]
131
- subject.class.accessible_by(ability).must_be :empty?
132
- end
133
- it 'takes the most permissive of roles' do
134
- role_1.test_locks = [ subject_type_lock(subject.class, false) ]
135
- role_2.test_locks = [ subject_type_lock(subject.class, true) ]
136
- subject.class.accessible_by(ability).must_include subject_test_1
137
- subject.class.accessible_by(ability).must_include subject_test_2
138
- end
139
- end
140
-
141
- describe 'on user' do
142
- it 'overrides default lock' do
143
- user.test_locks = [ subject_type_lock(subject.class, false) ]
144
- subject.class.accessible_by(ability).must_be :empty?
145
- end
146
- it 'overrides role locks' do
147
- role_1.test_locks = [ subject_type_lock(subject.class, false) ]
148
- user.test_locks = [ subject_type_lock(subject.class, true) ]
149
- subject.class.accessible_by(ability).must_include subject_test_1
150
- subject.class.accessible_by(ability).must_include subject_test_2
151
- end
152
- end
31
+ it 'replace existing locks with new attributes' do
32
+ MySubject.default_locks.detect{ |l| l.action == :read }.outcome.must_equal false
153
33
  end
154
34
 
155
- # ---------------------------------------------------------------------
156
-
157
- describe 'subject_id lock' do
158
- describe 'on roles' do
159
- it 'overrides default lock' do
160
- role_1.test_locks = [ subject_lock(subject_test_1, false) ]
161
- subject.class.accessible_by(ability).wont_include subject_test_1
162
- end
163
-
164
- it 'overrides default negative lock' do
165
- subject.class.stub(:default_locks, [ subject_type_lock(subject_test_1.class, false) ]) do
166
- role_1.test_locks = [ subject_lock(subject_test_1, true) ]
167
- subject.class.accessible_by(ability).must_include subject_test_1
168
- end
169
- end
170
-
171
- it 'overrides subject_type lock' do
172
- role_1.test_locks = [ subject_type_lock(subject_test_2.class, false) ]
173
- role_2.test_locks = [ subject_lock(subject_test_2, true) ]
174
- subject.class.accessible_by(ability).must_include subject_test_2
175
- end
176
-
177
- it 'overrides default negative lock' do
178
- subject.class.stub(:default_locks, [ subject_type_lock(subject_test_2.class, false) ]) do
179
- role_2.test_locks = [ subject_lock(subject_test_2, true) ]
180
- subject.class.accessible_by(ability).wont_include subject_test_1
181
- subject.class.accessible_by(ability).must_include subject_test_2
182
- end
183
- end
184
-
185
- it 'takes the most permissive of roles' do
186
- role_1.test_locks = [ subject_lock(subject_test_2, false) ]
187
- role_2.test_locks = [ subject_lock(subject_test_2, true) ]
188
- subject.class.accessible_by(ability).must_include subject_test_2
189
- end
190
- end
191
-
192
- describe 'on user' do
193
- it 'overrides default lock' do
194
- user.test_locks = [ subject_lock(subject_test_1, false) ]
195
- subject.class.accessible_by(ability).wont_include subject_test_1
196
- subject.class.accessible_by(ability).must_include subject_test_2
197
- end
198
-
199
- it 'overrides subject_type lock' do
200
- user.test_locks = [ subject_type_lock(subject_test_1.class, true), subject_lock(subject_test_1, false) ]
201
- subject.class.accessible_by(ability).wont_include subject_test_1
202
- end
203
-
204
- it 'overrides role locks' do
205
- role_1.test_locks = [ subject_lock(subject_test_2, false) ]
206
- user.test_locks = [ subject_lock(subject_test_2, true) ]
207
- subject.class.accessible_by(ability).must_include subject_test_2
208
- end
209
-
210
- it 'overrides default negative lock' do
211
- subject.class.stub(:default_locks, [ subject_type_lock(subject_test_2.class, false) ]) do
212
- user.test_locks = [ subject_lock(subject_test_2, true) ]
213
- subject.class.accessible_by(ability).must_include subject_test_2
214
- end
215
- end
216
- end
35
+ it 'replaces existing locks with new one' do
36
+ MySubject.default_locks.detect{ |l| l.action == :read }.class.must_equal MyLock1
217
37
  end
218
-
219
38
  end
39
+
220
40
  end
221
41
  end
222
-
223
42
  end
@@ -1,86 +1,161 @@
1
- class TestLock
2
- include Mongoid::Document
3
- include MongoidAbility::Lock
1
+ module MongoidAbility
2
+ class MyLock
3
+ include Mongoid::Document
4
+ include MongoidAbility::Lock
5
+ embedded_in :owner, polymorphic: true
6
+ end
4
7
 
5
- embedded_in :owner, polymorphic: true
6
- end
8
+ class MyLock1 < MyLock
9
+ def calculated_outcome opts={}
10
+ opts.fetch(:override, outcome)
11
+ end
12
+ end
7
13
 
8
- class TestLockSub < TestLock
9
- end
14
+ # ---------------------------------------------------------------------
10
15
 
11
- # ---------------------------------------------------------------------
16
+ class MySubject
17
+ include Mongoid::Document
18
+ include MongoidAbility::Subject
12
19
 
13
- class TestOwnerSuper
14
- include Mongoid::Document
15
- include MongoidAbility::Owner
20
+ default_lock MyLock, :read, true
21
+ default_lock MyLock1, :update, false
22
+ end
16
23
 
17
- embeds_many :test_locks, class_name: 'TestLock', as: :owner
18
- end
24
+ class MySubject1 < MySubject
25
+ default_lock MyLock, :read, false
26
+ end
19
27
 
20
- class TestOwner < TestOwnerSuper
21
- end
28
+ class MySubject2 < MySubject1
29
+ end
22
30
 
23
- # ---------------------------------------------------------------------
31
+ # ---------------------------------------------------------------------
24
32
 
25
- class SubjectTest
26
- include Mongoid::Document
27
- include MongoidAbility::Subject
33
+ class MyOwner
34
+ include Mongoid::Document
35
+ include MongoidAbility::Owner
28
36
 
29
- default_lock :read, true
30
- end
37
+ embeds_many :my_locks, class_name: 'MongoidAbility::MyLock', as: :owner
38
+ has_and_belongs_to_many :my_roles
31
39
 
32
- class SubjectTestOne < SubjectTest
33
- end
40
+ def self.locks_relation_name
41
+ :my_locks
42
+ end
34
43
 
35
- class SubjectTestTwo < SubjectTest
36
- end
44
+ def self.inherit_from_relation_name
45
+ :my_roles
46
+ end
47
+ end
37
48
 
38
- class SubjectSingleTest
39
- include Mongoid::Document
40
- include MongoidAbility::Subject
49
+ class MyOwner1 < MyOwner
50
+ end
41
51
 
42
- default_lock :read, true
43
- end
52
+ # ---------------------------------------------------------------------
44
53
 
45
- # ---------------------------------------------------------------------
54
+ class MyRole
55
+ include Mongoid::Document
56
+ include MongoidAbility::Owner
46
57
 
47
- class TestAbilityResolverSubject
48
- include Mongoid::Document
49
- include MongoidAbility::Subject
58
+ embeds_many :my_locks, class_name: 'MongoidAbility::MyLock', as: :owner
59
+ has_and_belongs_to_many :my_owners
50
60
 
51
- default_lock :read, true
52
- end
53
-
54
- class TestAbilitySubjectSuper2
55
- include Mongoid::Document
56
- include MongoidAbility::Subject
61
+ def self.locks_relation_name
62
+ :my_locks
63
+ end
64
+ end
57
65
 
58
- default_lock :read, false
59
- default_lock :update, true
66
+ class MyRole1 < MyRole
67
+ end
60
68
  end
61
69
 
62
- class TestAbilitySubjectSuper1 < TestAbilitySubjectSuper2
63
- end
64
70
 
65
- class TestAbilitySubject < TestAbilitySubjectSuper1
66
- end
67
71
 
68
- # ---------------------------------------------------------------------
69
72
 
70
- class TestRole
71
- include Mongoid::Document
72
- include MongoidAbility::Owner
73
73
 
74
- field :name, type: String
75
74
 
76
- embeds_many :test_locks, class_name: 'TestLock', as: :owner
77
- has_and_belongs_to_many :users, class_name: 'TestUser'
78
- end
79
-
80
- class TestUser
81
- include Mongoid::Document
82
- include MongoidAbility::Owner
83
75
 
84
- embeds_many :test_locks, class_name: 'TestLock', as: :owner
85
- has_and_belongs_to_many :roles, class_name: 'TestRole'
86
- end
76
+ # class TestLock
77
+ # include Mongoid::Document
78
+ # include MongoidAbility::Lock
79
+ #
80
+ # embedded_in :owner, polymorphic: true
81
+ # end
82
+ #
83
+ # class TestLockSub < TestLock
84
+ # end
85
+ #
86
+ # # ---------------------------------------------------------------------
87
+ #
88
+ # class TestOwnerSuper
89
+ # include Mongoid::Document
90
+ # include MongoidAbility::Owner
91
+ #
92
+ # embeds_many :test_locks, class_name: 'TestLock', as: :owner
93
+ # end
94
+ #
95
+ # class TestOwner < TestOwnerSuper
96
+ # end
97
+ #
98
+ # # ---------------------------------------------------------------------
99
+ #
100
+ # class SubjectTest
101
+ # include Mongoid::Document
102
+ # include MongoidAbility::Subject
103
+ #
104
+ # default_lock :read, true
105
+ # end
106
+ #
107
+ # class SubjectTestOne < SubjectTest
108
+ # end
109
+ #
110
+ # class SubjectTestTwo < SubjectTest
111
+ # end
112
+ #
113
+ # class SubjectSingleTest
114
+ # include Mongoid::Document
115
+ # include MongoidAbility::Subject
116
+ #
117
+ # default_lock :read, true
118
+ # end
119
+ #
120
+ # # ---------------------------------------------------------------------
121
+ #
122
+ # class TestAbilityResolverSubject
123
+ # include Mongoid::Document
124
+ # include MongoidAbility::Subject
125
+ #
126
+ # default_lock :read, true
127
+ # end
128
+ #
129
+ # class TestAbilitySubjectSuper2
130
+ # include Mongoid::Document
131
+ # include MongoidAbility::Subject
132
+ #
133
+ # default_lock :read, false
134
+ # default_lock :update, true
135
+ # end
136
+ #
137
+ # class TestAbilitySubjectSuper1 < TestAbilitySubjectSuper2
138
+ # end
139
+ #
140
+ # class TestAbilitySubject < TestAbilitySubjectSuper1
141
+ # end
142
+ #
143
+ # # ---------------------------------------------------------------------
144
+ #
145
+ # class TestRole
146
+ # include Mongoid::Document
147
+ # include MongoidAbility::Owner
148
+ #
149
+ # field :name, type: String
150
+ #
151
+ # embeds_many :test_locks, class_name: 'TestLock', as: :owner
152
+ # has_and_belongs_to_many :users, class_name: 'TestUser'
153
+ # end
154
+ #
155
+ # class TestUser
156
+ # include Mongoid::Document
157
+ # include MongoidAbility::Owner
158
+ #
159
+ # embeds_many :test_locks, class_name: 'TestLock', as: :owner
160
+ # has_and_belongs_to_many :roles, class_name: 'TestRole'
161
+ # end