troles 0.5.0 → 0.5.1
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile.lock +1 -1
- data/README.textile +75 -16
- data/VERSION +1 -1
- data/lib/trole/adapters/active_record/config.rb +3 -3
- data/lib/trole/adapters/mongoid/config.rb +5 -5
- data/lib/trole/config.rb +2 -2
- data/lib/trole_groups.rb +10 -0
- data/lib/trole_groups/READ THIS.textile +4 -0
- data/lib/trole_groups/Rolegroups design.textile +218 -0
- data/lib/trole_groups/adapters/active_record.rb +8 -0
- data/lib/trole_groups/adapters/active_record/config.rb +0 -0
- data/lib/trole_groups/adapters/active_record/storage.rb +0 -0
- data/lib/trole_groups/adapters/active_record/strategy.rb +11 -0
- data/lib/trole_groups/adapters/mongoid.rb +8 -0
- data/lib/trole_groups/adapters/mongoid/config.rb +0 -0
- data/lib/trole_groups/api.rb +29 -0
- data/lib/trole_groups/api/cache.rb +13 -0
- data/lib/trole_groups/api/config.rb +4 -0
- data/lib/trole_groups/api/core.rb +50 -0
- data/lib/trole_groups/api/event.rb +29 -0
- data/lib/trole_groups/api/read.rb +56 -0
- data/lib/trole_groups/api/validation.rb +44 -0
- data/lib/trole_groups/api/write.rb +60 -0
- data/lib/trole_groups/config.rb +134 -0
- data/lib/trole_groups/config/schema.rb +65 -0
- data/lib/trole_groups/config/schema/helpers.rb +11 -0
- data/lib/trole_groups/config/schema/role_group_helpers.rb +11 -0
- data/lib/trole_groups/config/valid_role_groups.rb +21 -0
- data/lib/trole_groups/macros.rb +42 -0
- data/lib/trole_groups/macros/configuration.rb +89 -0
- data/lib/trole_groups/macros/configuration/base_loader.rb +35 -0
- data/lib/trole_groups/macros/configuration/config_loader.rb +19 -0
- data/lib/trole_groups/macros/configuration/storage_loader.rb +20 -0
- data/lib/trole_groups/macros/configuration/strategy_loader.rb +38 -0
- data/lib/trole_groups/macros/static_roles.rb +9 -0
- data/lib/trole_groups/macros/strategy_options.rb +21 -0
- data/lib/trole_groups/operations.rb +25 -0
- data/lib/trole_groups/operations/read.rb +36 -0
- data/lib/trole_groups/operations/write.rb +42 -0
- data/lib/trole_groups/storage.rb +27 -0
- data/lib/trole_groups/storage/base_many.rb +93 -0
- data/lib/trole_groups/storage/embed_many.rb +58 -0
- data/lib/trole_groups/storage/ref_many.rb +47 -0
- data/lib/trole_groups/strategy.rb +30 -0
- data/lib/troles/adapters/active_record/config.rb +32 -9
- data/lib/troles/adapters/mongoid/config.rb +7 -7
- data/lib/troles/common/api/core.rb +1 -1
- data/lib/troles/common/config.rb +49 -14
- data/lib/troles/common/config/schema.rb +17 -23
- data/lib/troles/common/config/schema/helpers.rb +77 -0
- data/lib/troles/common/config/schema/role_helpers.rb +27 -0
- data/lib/troles/common/config/static_roles.rb +4 -4
- data/lib/troles/common/macros.rb +4 -4
- data/lib/troles/common/macros/configuration.rb +8 -8
- data/lib/troles/common/macros/strategy_options.rb +4 -4
- data/lib/troles/common/storage.rb +1 -0
- data/lib/troles/config.rb +2 -2
- data/lib/troles/storage/ref_many.rb +2 -3
- data/spec/active_record/models/ref_many.rb +3 -0
- data/spec/active_record/strategies/many/ref_many_spec.rb +2 -1
- data/spec/generic/models/role.rb +2 -1
- data/spec/trole_groups/api/core_api_spec.rb +14 -0
- data/spec/trole_groups/api/read_api_spec.rb +36 -0
- data/spec/trole_groups/api/write_api_spec.rb +19 -0
- data/spec/trole_groups/api_spec.rb +27 -0
- data/spec/trole_groups/generic/models.rb +3 -0
- data/spec/trole_groups/generic/models/role_group.rb +44 -0
- data/spec/trole_groups/generic/models/user.rb +9 -0
- data/spec/trole_groups/strategies/ref_many.rb +51 -0
- data/spec/trole_groups/strategy_helper.rb +9 -0
- data/spec/trole_groups_spec.rb +11 -0
- data/spec/trole_spec_helper.rb +9 -0
- data/spec/troles/api_spec.rb +12 -18
- data/troles.gemspec +52 -4
- metadata +85 -37
- data/development.sqlite3 +0 -0
- data/lib/troles/common/config/schema_helpers.rb +0 -95
data/Gemfile.lock
CHANGED
data/README.textile
CHANGED
@@ -6,23 +6,61 @@ The project currently consists of:
|
|
6
6
|
|
7
7
|
* Trole - for single role strategies
|
8
8
|
* Troles - for many roles strategies
|
9
|
+
* TroleGroups - for groups of roles
|
9
10
|
|
10
11
|
The Troles project uses _role caching_ to optimize performance!
|
11
12
|
The roles list cache of a role subject (fx a user) is only updated (retrieved from data store) when the roles of the role subject changes!
|
12
13
|
|
13
14
|
Note: Troles is a full redesign of _roles generic_ and company, using lessons learned. Troles uses a much cleaner design. It is aimed at being easy to extend and easy to create adapters for etc.
|
14
15
|
|
15
|
-
h2. Status June
|
16
|
+
h2. Status June 7, 2011
|
16
17
|
|
17
|
-
|
18
|
-
|
19
|
-
|
18
|
+
I'm now in the process of implementing TroleGroups! Finally a fully integrated role groups solution for Ruby and Rails ;)
|
19
|
+
Due to the flexible design ot troles and trole, I can reuse the same infrastructure/design/architecture to implement trole_groups!
|
20
|
+
*Yiii...haaa!*
|
21
|
+
|
22
|
+
"A RoleGroup is simply another role_subject and can thus be configured with a given role strategy!"
|
20
23
|
|
21
|
-
|
24
|
+
Simple and Sweet :)
|
22
25
|
|
23
|
-
The
|
26
|
+
h2. The Ruby Class Decorator (RCD) pattern is born!!!
|
24
27
|
|
25
|
-
|
28
|
+
I realized a while ago that I had come upon a very cool kind of "class decorator" design pattern that can be generalized to any gem that "decorates" a class (or perhaps multiple classes) with certain behavior. Gems such as _act_as_xxx_ come to mind fx.
|
29
|
+
|
30
|
+
I will soon try to generalize this pattern into a separate project and then have trole, troles and trole_groups all use this to leverage their functionality. Also, I will make use of an idea that I just had while taking a cold shower (try it sometime if you have a mind block!).
|
31
|
+
The idea is to have an internal default API, and an exposed API that by default is a reflection of the internal API. However the user is free to block parts of the API from being loaded or define his own external API that utilizes the inner API.
|
32
|
+
|
33
|
+
Since this is a general purpose decorator pattern, there should also be a kind of Index where you can see which decorators have been applied to an object and what API each such decorator exposes! Cool stuff!!!!
|
34
|
+
|
35
|
+
Some example usage:
|
36
|
+
<pre>
|
37
|
+
return if !User.has_decorator?(:troles_group)
|
38
|
+
# do some trole group stuff!!!
|
39
|
+
|
40
|
+
# later ...
|
41
|
+
|
42
|
+
# list all decorators currently applied to the User class
|
43
|
+
puts User.decorators
|
44
|
+
|
45
|
+
# print the methods of the public Write API for the :troles_group decorator :)
|
46
|
+
puts User.decorator(:troles_group).public_api(:write).methods.sort
|
47
|
+
|
48
|
+
# print the methods of the internal Write API for the :troles_group decorator :)
|
49
|
+
puts User.decorator(:troles_group).internal_api(:write).methods.sort
|
50
|
+
</pre>
|
51
|
+
|
52
|
+
I will use the new Decorator API very soon... sth like this:
|
53
|
+
|
54
|
+
<pre>
|
55
|
+
User.decorator(:trole_groups).configure(:strategy) :ref_one do |strategy|
|
56
|
+
strategy.orm = :mongoid
|
57
|
+
strategy.auto_load = true
|
58
|
+
end.configure!
|
59
|
+
</pre>
|
60
|
+
|
61
|
+
Awesome!
|
62
|
+
|
63
|
+
h3. Yard documentation
|
26
64
|
|
27
65
|
I'm using "Yard":http://rubydoc.info/docs/yard/file/docs/GettingStarted.md for documentation.
|
28
66
|
|
@@ -197,17 +235,17 @@ A custom Config class for _:single_ role strategies using _Mongoid_ could look s
|
|
197
235
|
module Trole::Mongoid
|
198
236
|
class Config < Troles::Common::Config
|
199
237
|
|
200
|
-
def initialize
|
238
|
+
def initialize subject_class, options = {}
|
201
239
|
super
|
202
240
|
end
|
203
241
|
|
204
242
|
def configure_relation
|
205
243
|
case strategy
|
206
244
|
when :ref_one
|
207
|
-
has_one_for
|
208
|
-
belongs_to_for
|
245
|
+
has_one_for subject_class, object_model
|
246
|
+
belongs_to_for object_model, subject_class
|
209
247
|
when :embed_one
|
210
|
-
embeds_one_for
|
248
|
+
embeds_one_for subject_class, object_model
|
211
249
|
end
|
212
250
|
end
|
213
251
|
|
@@ -218,7 +256,7 @@ module Trole::Mongoid
|
|
218
256
|
when :string_one
|
219
257
|
String
|
220
258
|
end
|
221
|
-
|
259
|
+
subject_class.send(:field, role_field, type) if type
|
222
260
|
end
|
223
261
|
</pre>
|
224
262
|
|
@@ -231,7 +269,7 @@ Example: Config class for :many roles strategies with _Mongoid_
|
|
231
269
|
module Troles::Mongoid
|
232
270
|
class Config < Troles::Common::Config
|
233
271
|
|
234
|
-
def initialize
|
272
|
+
def initialize subject_class, options = {}
|
235
273
|
super
|
236
274
|
end
|
237
275
|
|
@@ -248,7 +286,7 @@ module Troles::Mongoid
|
|
248
286
|
when :string_many
|
249
287
|
String
|
250
288
|
end
|
251
|
-
|
289
|
+
subject_class.send(:field, role_field, type: => type) if type
|
252
290
|
end
|
253
291
|
</pre>
|
254
292
|
|
@@ -497,9 +535,9 @@ User.troles_strategy :bit_one, :orm => :active_record do |c|
|
|
497
535
|
c.auto_load = false
|
498
536
|
c.valid_roles = [:troll_commander, :troll_warrior]
|
499
537
|
|
500
|
-
c.
|
538
|
+
c.auto_config[:relations] = false # to take over control of setting up model relationships
|
501
539
|
|
502
|
-
end.configure! :role_model => 'Troll', :
|
540
|
+
end.configure! :role_model => 'Troll', :role_join_model => 'UserTroll'
|
503
541
|
</pre>
|
504
542
|
|
505
543
|
Enjoy :)
|
@@ -511,6 +549,9 @@ The following is a list of the global Troles common configuration options:
|
|
511
549
|
* default_orm
|
512
550
|
* auto_load (true|false)
|
513
551
|
* log_on (true|false)
|
552
|
+
* auto_config[:models] (true|false)
|
553
|
+
* auto_config[:fields] (true|false)
|
554
|
+
* auto_config[:relations] (true|false)
|
514
555
|
|
515
556
|
Examples:
|
516
557
|
|
@@ -526,6 +567,24 @@ Ensures the adapter is autoloaded from the troles internal _/adapter_ folder. Le
|
|
526
567
|
|
527
568
|
Turns on some logging to make it easier to debug what goes on behind the curtain (note: to be improved...).
|
528
569
|
|
570
|
+
@Troles::Common::Config.auto_config[:models] = false@
|
571
|
+
|
572
|
+
Disables troles auto configuration of models, allowing you full control.
|
573
|
+
|
574
|
+
@Troles::Common::Config.auto_config[:relations] = false@
|
575
|
+
|
576
|
+
Disables troles auto configuration of model relationships (has_many, belongs_to and such), allowing you full control.
|
577
|
+
|
578
|
+
@Troles::Common::Config.auto_config[:fields] = false@
|
579
|
+
|
580
|
+
Disables troles auto configuration of model fields (for data stores such as Data Mapper, Mongoid etc that have the concept of data fields), allowing you full control.
|
581
|
+
|
582
|
+
Note: For all the global on/off options you can opt to use same option on an individual strategy basis as part of an individual strategy configuration.
|
583
|
+
|
584
|
+
In the strategy Config class they can be used like this
|
585
|
+
|
586
|
+
@if auto_config?(:fields)@
|
587
|
+
|
529
588
|
h2. Other notes on Application-User control
|
530
589
|
|
531
590
|
_troles_ will be part of a larger project under development that will go under the name "dancing tango with trolls". This will be a rework of _cream_ and _cancan-permits_ that will target use in apllications with multiple user accounts and multiple sub applications. In this new system, _dancing_ will be the replacement of _cream_ and _tango_ the replacement of _cancan-permits_. I hope to give a talk on RubyConf 2011 about this system.
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.5.
|
1
|
+
0.5.1
|
@@ -1,15 +1,15 @@
|
|
1
1
|
module Trole::ActiveRecord
|
2
2
|
class Config < Troles::Common::Config
|
3
3
|
|
4
|
-
def initialize
|
4
|
+
def initialize subject_class, options = {}
|
5
5
|
super
|
6
6
|
end
|
7
7
|
|
8
8
|
def configure_relation
|
9
9
|
case strategy
|
10
10
|
when :ref_one
|
11
|
-
belongs_to_for
|
12
|
-
has_many_for
|
11
|
+
belongs_to_for subject_class, object_model, :key => main_field
|
12
|
+
has_many_for object_model, subject_class
|
13
13
|
when :embed_one
|
14
14
|
raise "EmbedOne is currently not supported by the Active Record adapter. It will be soon..."
|
15
15
|
#clazz.send(:embeds_many, role_model_key, :class_name => role_model_class_name)
|
@@ -1,17 +1,17 @@
|
|
1
1
|
module Trole::Mongoid
|
2
2
|
class Config < Troles::Common::Config
|
3
3
|
|
4
|
-
def initialize
|
4
|
+
def initialize subject_class, options = {}
|
5
5
|
super
|
6
6
|
end
|
7
7
|
|
8
8
|
def configure_relation
|
9
9
|
case strategy
|
10
10
|
when :ref_one
|
11
|
-
has_one_for
|
12
|
-
belongs_to_for
|
11
|
+
has_one_for subject_class, object_model
|
12
|
+
belongs_to_for object_model, subject_class
|
13
13
|
when :embed_one
|
14
|
-
embeds_one
|
14
|
+
embeds_one subject_class, object_model
|
15
15
|
end
|
16
16
|
end
|
17
17
|
|
@@ -22,7 +22,7 @@ module Trole::Mongoid
|
|
22
22
|
when :string_one
|
23
23
|
String
|
24
24
|
end
|
25
|
-
|
25
|
+
subject_class.send(:field, role_field, type) if type
|
26
26
|
end
|
27
27
|
|
28
28
|
protected
|
data/lib/trole/config.rb
CHANGED
data/lib/trole_groups.rb
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
require 'troles/common'
|
2
|
+
require 'troles/macros'
|
3
|
+
|
4
|
+
module TroleGroups
|
5
|
+
autoload :Config, 'trole_groups/config'
|
6
|
+
autoload :Api, 'trole_groups/api'
|
7
|
+
autoload :Operations, 'trole_groups/operations'
|
8
|
+
autoload :Strategy, 'trole_groups/strategy'
|
9
|
+
autoload :Storage, 'trole_groups/storage'
|
10
|
+
end
|
@@ -0,0 +1,218 @@
|
|
1
|
+
h1. Role groups
|
2
|
+
|
3
|
+
A RoleGroup is simply another role_subject and can thus be configured with a given role strategy! Sweet :)
|
4
|
+
|
5
|
+
In some scenarios it makes sense to allow a user to be assigned one or more role groups.
|
6
|
+
|
7
|
+
<pre>
|
8
|
+
Rolegroup.get(:bloggers).set_roles :blog_admin, :admin
|
9
|
+
Rolegroup.get(:super_admin).set_roles :blog_admin, :admin
|
10
|
+
Rolegroup.create(:super_admin, :roles => [:blog_admin, :admin])
|
11
|
+
|
12
|
+
Rolegroup.create(:super_admin).set_roles :blog_admin, :admin
|
13
|
+
</pre>
|
14
|
+
|
15
|
+
<pre>
|
16
|
+
user.rolegroups << [:bloggers, :admins]
|
17
|
+
user.in_rolegroup? :bloggers
|
18
|
+
</pre>
|
19
|
+
|
20
|
+
many rolegroups from a set of valid rolegroups
|
21
|
+
|
22
|
+
|
23
|
+
Multiple roles strategy
|
24
|
+
|
25
|
+
Schema
|
26
|
+
Integer (bitmap) field on the User class
|
27
|
+
String of comma delimited role groups on User class
|
28
|
+
References to multiple RoleGroups
|
29
|
+
Embeds multiple RoleGroups (document store)
|
30
|
+
|
31
|
+
Field stored in the datastore
|
32
|
+
|
33
|
+
trolegroups
|
34
|
+
|
35
|
+
The field is named trolegroups, in order not to conflict with the method #rolegroups used in the role group DSL.
|
36
|
+
|
37
|
+
These strategies can be named:
|
38
|
+
|
39
|
+
bit_many
|
40
|
+
string_many
|
41
|
+
ref_many
|
42
|
+
embed_many
|
43
|
+
|
44
|
+
These strategies can be implemented for any data store using any schema format.
|
45
|
+
|
46
|
+
<pre>
|
47
|
+
User
|
48
|
+
include Troles::GroupAdapter::RefMany
|
49
|
+
</pre>
|
50
|
+
|
51
|
+
When a user is assigned a given role group, he is automatically treated as having the roles of that role group. The role group cache of the user thus changes when he is assigned or removed from a role group.
|
52
|
+
|
53
|
+
The role group however can also change, and this will effect all users assigned to that role group. The RoleGroups::EventManager must be called in all these cases.
|
54
|
+
|
55
|
+
Roles API
|
56
|
+
The Roles API can be divided into
|
57
|
+
|
58
|
+
* Read operations
|
59
|
+
* Write operations and related functionality
|
60
|
+
|
61
|
+
RoleGroup Read API
|
62
|
+
These methods are available on the User instance
|
63
|
+
|
64
|
+
<pre>
|
65
|
+
# any? on rolegroups_list
|
66
|
+
def in_rolegroup? rolegroup
|
67
|
+
|
68
|
+
# rolegroup_list has one element which is rolegroup
|
69
|
+
def is_rolegroup? rolegroup
|
70
|
+
|
71
|
+
# subtraction of role_groups from rolegroups_list is empty
|
72
|
+
def has_all_rolegroups? rolegroups
|
73
|
+
|
74
|
+
# union of rolegroups and rolegroups_list is not empty
|
75
|
+
def in_any_rolegroup? rolegroups
|
76
|
+
|
77
|
+
# return roles of that rolegroup
|
78
|
+
def roles_of rolegroup
|
79
|
+
|
80
|
+
# return Set of symbols,where each symbol is a rolegroup name
|
81
|
+
# This set should be cached and only invalidated when the user has a change of roles
|
82
|
+
def rolegroups_list
|
83
|
+
</pre>
|
84
|
+
|
85
|
+
RoleGroup Write API
|
86
|
+
|
87
|
+
The User class should have an event trigger after save to see if the roles were changed.
|
88
|
+
If the roles were changed, an even should be sent to an event manager to handle this, invalidating role caches etc.
|
89
|
+
|
90
|
+
<pre>
|
91
|
+
User
|
92
|
+
after_save: update_role_groups # add event handler
|
93
|
+
</pre>
|
94
|
+
|
95
|
+
These methods are available on the User instance
|
96
|
+
|
97
|
+
<pre>
|
98
|
+
# a change to the roles of the user should be published to an event handler
|
99
|
+
# this can be used to update both the Role cache of the user and fx the RolePermit cache.
|
100
|
+
# Both (and potentially others, fx for Role Groups) can subscribe to this event!
|
101
|
+
def update_role_groups
|
102
|
+
publish_change(:role_groups) if field_changed?(rolegroups_field)
|
103
|
+
end
|
104
|
+
|
105
|
+
# check if a field on the model changed
|
106
|
+
# See http://api.rubyonrails.org/classes/ActiveModel/Dirty.html
|
107
|
+
def field_changed? name
|
108
|
+
send :“#{name}_changed?”
|
109
|
+
end
|
110
|
+
|
111
|
+
# can be customized
|
112
|
+
# here uses singleton EventManager
|
113
|
+
def publish_change event
|
114
|
+
Roles::EventManager.publish_change event, :from => self
|
115
|
+
end
|
116
|
+
|
117
|
+
# return the role field used, fx :rolegroup_value etc.
|
118
|
+
# should NOT be mutable
|
119
|
+
def rolegroups_field
|
120
|
+
:rolegroup_value
|
121
|
+
end
|
122
|
+
|
123
|
+
def add_rolegroup
|
124
|
+
role_groups << role
|
125
|
+
end
|
126
|
+
|
127
|
+
def remove_rolegroup
|
128
|
+
role_groups << role
|
129
|
+
end
|
130
|
+
|
131
|
+
# should return a RoleGroups::Operations object
|
132
|
+
def role_groups
|
133
|
+
TRoles::RoleGroups::Operations.new(self)
|
134
|
+
|
135
|
+
class TRoles::RoleGroups:: Operations
|
136
|
+
include ReadOperations
|
137
|
+
include WriteOperations
|
138
|
+
|
139
|
+
def initialize user
|
140
|
+
end
|
141
|
+
end
|
142
|
+
</pre>
|
143
|
+
|
144
|
+
<pre>
|
145
|
+
module TRoles: RoleGroups::ReadOperations
|
146
|
+
# check if any of the rolegroups have the given role
|
147
|
+
|
148
|
+
def contains? role_group
|
149
|
+
list.include? role_group
|
150
|
+
end
|
151
|
+
alias_method :includes?, :contains?
|
152
|
+
|
153
|
+
# symbol list of role groups
|
154
|
+
def list
|
155
|
+
|
156
|
+
# Set of roles from all role groups
|
157
|
+
def roles_list
|
158
|
+
|
159
|
+
def get *role_groups
|
160
|
+
|
161
|
+
end
|
162
|
+
</pre>
|
163
|
+
|
164
|
+
<pre>
|
165
|
+
module TRoles: RoleGroups::WriteOperations
|
166
|
+
def + # add role group
|
167
|
+
alias_method <<
|
168
|
+
|
169
|
+
def - # remove role groups
|
170
|
+
end
|
171
|
+
|
172
|
+
user.roles_groups.get(:bloggers) => returns :bloggers if in roles_list, or raises error
|
173
|
+
user.roles_groups.get(:bloggers, :admins) => returns [:bloggers, :admins], or error
|
174
|
+
|
175
|
+
if user.role_groups.roles_list == [:admin, :blogger]
|
176
|
+
if user.role_groups.have_role? :blogger
|
177
|
+
|
178
|
+
user.role_groups.add :bloggers
|
179
|
+
user.role_groups << :bloggers
|
180
|
+
user.role_groups + [:bloggers, :editors]
|
181
|
+
user.role_groups - :admins
|
182
|
+
</pre>
|
183
|
+
|
184
|
+
Relational schema
|
185
|
+
|
186
|
+
<pre>
|
187
|
+
RoleGroup
|
188
|
+
has_many :roles
|
189
|
+
</pre>
|
190
|
+
|
191
|
+
<pre>
|
192
|
+
Role
|
193
|
+
belongs_to :role_group
|
194
|
+
belongs_to :user
|
195
|
+
</pre>
|
196
|
+
|
197
|
+
If the RoleGroup is used in a Relational schema model, the RoleGroup should belong to a user and a Role should belong to a Group.
|
198
|
+
|
199
|
+
Roles field on RoleGroup
|
200
|
+
|
201
|
+
<pre>
|
202
|
+
RoleGroup
|
203
|
+
def valid_roles
|
204
|
+
|
205
|
+
belongs_to :user
|
206
|
+
field roles (String, Integer bitmap)
|
207
|
+
</pre>
|
208
|
+
|
209
|
+
In a non-relational schema model, the RoleGroup would still belong to a User but the roles could be a field of either String or Integer (bitmap) instead of a relation to a Role model.
|
210
|
+
If an integer bitmap is used, the bits would map onto the valid_roles list that returns a list of role symbols.
|
211
|
+
|
212
|
+
The valid_roles method should get the list of valid roles from a singleton such as TRoles::Configuration. The actual implementation could either use a static list, pull it from a yaml file or perhaps execute all_roles on Role.
|
213
|
+
|
214
|
+
<pre>
|
215
|
+
class Role
|
216
|
+
scope :role_list, lambda { all.map {|r| name.to_sym} }
|
217
|
+
end
|
218
|
+
</pre>
|