role_model 0.5.0 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.rdoc CHANGED
@@ -9,12 +9,12 @@ It works like this:
9
9
  # given a User class with a roles_mask attribute
10
10
  require 'rubygems'
11
11
  require 'role_model'
12
-
12
+
13
13
  class User
14
14
  attr_accessor :roles_mask # in real life this would be an persisted attribute
15
15
 
16
16
  include RoleModel
17
-
17
+
18
18
  # optionally set the integer attribute to store the roles in,
19
19
  # :roles_mask is the default
20
20
  roles_attribute :roles_mask
@@ -27,20 +27,20 @@ It works like this:
27
27
  #
28
28
  # Test drive (check the RDoc or source for additional finesse)
29
29
  #
30
-
30
+
31
31
  >> u = User.new
32
32
  => #<User ...>
33
-
33
+
34
34
  # role assignment
35
35
  >> u.roles = [:admin] # ['admin'] works as well
36
36
  => [:admin]
37
-
38
- # adding roles
37
+
38
+ # adding roles (remove via delete or re-assign)
39
39
  >> u.roles << :manager
40
40
  => [:admin, :manager]
41
41
 
42
42
  # querying roles...
43
-
43
+
44
44
  # get all valid roles that have been declared
45
45
  >> User.valid_roles
46
46
  => [:admin, :manager, :author]
@@ -48,21 +48,25 @@ It works like this:
48
48
  # ... retrieve all assigned roles
49
49
  >> u.roles # aliased to role_symbols for DeclarativeAuthorization
50
50
  => [:admin, :manager]
51
-
51
+
52
52
  # ... check for individual roles
53
53
  >> u.has_role? :author # has_role? is also aliased to is?
54
54
  => false
55
-
55
+
56
56
  # ... check for multiple roles
57
57
  >> u.has_any_role? :author, :manager # has_any_role? is also aliased to is_any_of?
58
58
  => true
59
-
59
+
60
60
  >> u.has_all_roles? :author, :manager # has_all_roles? is also aliased to is?
61
61
  => false
62
-
62
+
63
63
  # see the internal bitmask representation (3 = 0b0011)
64
64
  >> u.roles_mask
65
65
  => 3
66
+
67
+ # see the role mask for a certain role(s)
68
+ >> User.mask_for :admin, :author
69
+ => 5
66
70
 
67
71
  Once you have included RoleModel, your model is perfectly fit to be used
68
72
  together with a role-based authorization solution, such as
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.5.0
1
+ 0.6.0
@@ -28,5 +28,17 @@ module RoleModel
28
28
  def roles(*roles)
29
29
  self.valid_roles = Array[*roles].flatten.map { |r| r.to_sym }
30
30
  end
31
+
32
+ def mask_for(*roles)
33
+ (Array[*roles].map {|r|
34
+ r.respond_to?(:each) ? r.to_a : r
35
+ }.flatten.map { |r|
36
+ r.to_sym
37
+ } & valid_roles).map { |r|
38
+ 2**valid_roles.index(r)
39
+ }.inject { |sum, bitvalue|
40
+ sum + bitvalue
41
+ } || 0
42
+ end
31
43
  end
32
44
  end
@@ -3,7 +3,7 @@ module RoleModel
3
3
 
4
4
  # assign roles
5
5
  def roles=(*roles)
6
- self.send("#{self.class.roles_attribute_name}=", (Array[*roles].flatten.map { |r| r.to_sym } & self.class.valid_roles).map { |r| 2**self.class.valid_roles.index(r) }.inject { |sum, bitvalue| sum + bitvalue })
6
+ self.send("#{self.class.roles_attribute_name}=", self.class.mask_for(*roles))
7
7
  end
8
8
 
9
9
  # query assigned roles
@@ -4,14 +4,22 @@ module RoleModel
4
4
  class Roles < ::Set # :nodoc:
5
5
  attr_reader :model_instance
6
6
 
7
- def initialize(sender, *roles)
8
- super(*roles)
7
+ def initialize(sender, roles)
8
+ super(roles)
9
9
  @model_instance = sender
10
10
  end
11
11
 
12
- def <<(role)
13
- model_instance.roles = super.to_a
12
+ def add(role)
13
+ roles = super
14
+ model_instance.roles = roles if model_instance
14
15
  self
15
16
  end
17
+ alias_method :<<, :add
18
+
19
+ def delete(role)
20
+ model_instance.roles = super(role.to_sym)
21
+ self
22
+ end
23
+
16
24
  end
17
25
  end
data/role_model.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{role_model}
8
- s.version = "0.5.0"
8
+ s.version = "0.6.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Martin Rehfeld"]
12
- s.date = %q{2010-08-17}
12
+ s.date = %q{2010-10-10}
13
13
  s.description = %q{Ever needed to assign roles to a model, say a User, and build conditional behaviour on top of that? Enter RoleModel -- roles have never been easier! Just declare your roles and you are done. Assigned roles will be stored as a bitmask.}
14
14
  s.email = %q{martin.rehfeld@glnetworks.de}
15
15
  s.extra_rdoc_files = [
@@ -126,6 +126,13 @@ describe RoleModel do
126
126
  subject.roles.should include(:bar)
127
127
  subject.should have(1).roles
128
128
  end
129
+
130
+ it "should allow reassigning the #roles value aka Roles object" do
131
+ subject.roles << :bar
132
+ subject.roles = subject.roles
133
+ subject.roles.should include(:foo, :bar)
134
+ subject.should have(2).roles
135
+ end
129
136
  end
130
137
  end
131
138
 
@@ -180,6 +187,47 @@ describe RoleModel do
180
187
  end
181
188
  end
182
189
 
190
+ describe "#delete" do
191
+ subject { model_class.new }
192
+
193
+ context "with roles :foo and :bar already assigned" do
194
+ before(:each) do
195
+ subject.roles = [:foo, :bar]
196
+ end
197
+
198
+ it "should delete a existing role given as a symbol" do
199
+ subject.roles.delete(:foo)
200
+ subject.roles.should_not include(:foo)
201
+ subject.should have(1).roles
202
+ end
203
+
204
+ it "should delete a existing role given as a string" do
205
+ subject.roles.delete('foo')
206
+ subject.roles.should_not include(:foo)
207
+ subject.should have(1).roles
208
+ end
209
+
210
+ it "should not change anything if a non existing role is given" do
211
+ subject.roles.delete(:third)
212
+ subject.roles.should include(:foo, :bar)
213
+ subject.should have(2).roles
214
+ end
215
+ end
216
+
217
+ context "without roles assigned" do
218
+ it "should have 0 roles if a role is given as a symbol" do
219
+ subject.roles.delete(:foo)
220
+ subject.should have(0).roles
221
+ end
222
+
223
+ it "should have 0 roles if a role is given as a string" do
224
+ subject.roles.delete('foo')
225
+ subject.should have(0).roles
226
+ end
227
+ end
228
+
229
+ end
230
+
183
231
  context "query for an individual role" do
184
232
  [:has_any_role?, :is_any_of?, :has_role?, :has_all_roles?, :is?, :has_roles?].each do |check_role_assignment_method|
185
233
  describe "##{check_role_assignment_method}" do
@@ -212,28 +260,14 @@ describe RoleModel do
212
260
  describe "##{check_role_assignment_method}" do
213
261
  subject { model_class.new }
214
262
 
215
- it "should return true when the given role was assigned" do
216
- subject.roles = :foo
217
- subject.send(check_role_assignment_method, :foo).should be_true
218
- end
219
-
220
263
  it "should return true when any of the given roles was assigned" do
221
- subject.roles = :foo
264
+ subject.roles = [:foo, :baz]
222
265
  subject.send(check_role_assignment_method, :foo, :bar).should be_true
223
266
  end
224
267
 
225
- it "should return false when the given role was not assigned" do
226
- subject.roles = :bar
227
- subject.send(check_role_assignment_method, :foo).should be_false
228
- end
229
-
230
- it "should return false when no role was assigned" do
231
- subject.send(check_role_assignment_method, :foo).should be_false
232
- subject.send(check_role_assignment_method, :bar).should be_false
233
- end
234
-
235
- it "should return false when asked for an undefined role" do
236
- subject.send(check_role_assignment_method, :baz).should be_false
268
+ it "should return false when none of the given roles were assigned" do
269
+ subject.roles = [:foo, :bar]
270
+ subject.send(check_role_assignment_method, :baz, :quux).should be_false
237
271
  end
238
272
  end
239
273
  end
@@ -242,33 +276,19 @@ describe RoleModel do
242
276
  describe "##{check_role_assignment_method}" do
243
277
  subject { model_class.new }
244
278
 
245
- it "should return true when the given role was assigned" do
246
- subject.roles = :foo
247
- subject.send(check_role_assignment_method, :foo).should be_true
248
- end
249
-
250
- it "should return true when all of the given roles was assigned" do
279
+ it "should return true when all of the given roles were assigned" do
251
280
  subject.roles = [:foo, :bar]
252
281
  subject.send(check_role_assignment_method, :foo, :bar).should be_true
253
282
  end
254
283
 
255
- it "should return false when not all of the given roles were assigned" do
284
+ it "should return false when only some of the given roles were assigned" do
256
285
  subject.roles = [:foo, :bar]
257
286
  subject.send(check_role_assignment_method, :bar, :baz).should be_false
258
287
  end
259
288
 
260
- it "should return false when the given role was not assigned" do
261
- subject.roles = :bar
262
- subject.send(check_role_assignment_method, :foo).should be_false
263
- end
264
-
265
- it "should return false when no role was assigned" do
266
- subject.send(check_role_assignment_method, :foo).should be_false
267
- subject.send(check_role_assignment_method, :bar).should be_false
268
- end
269
-
270
- it "should return false when asked for an undefined role" do
271
- subject.send(check_role_assignment_method, :baz).should be_false
289
+ it "should return false when none of the given roles were assigned" do
290
+ subject.roles = [:foo, :bar]
291
+ subject.send(check_role_assignment_method, :baz, :quux).should be_false
272
292
  end
273
293
  end
274
294
  end
@@ -346,4 +366,45 @@ describe RoleModel do
346
366
  end
347
367
  end
348
368
 
369
+ describe ".mask_for" do
370
+ subject { model_class.new }
371
+
372
+ before(:each) do
373
+ model_class.instance_eval do
374
+ attr_accessor :roles_mask
375
+ attr_accessor :custom_roles_mask
376
+ include RoleModel
377
+ roles :foo, :bar, :third
378
+ end
379
+ end
380
+
381
+ context "passing" do
382
+ it "should return the role mask of a role" do
383
+ subject.class.mask_for(:foo).should == 1
384
+ subject.class.mask_for(:bar).should == 2
385
+ subject.class.mask_for(:third).should == 4
386
+ end
387
+
388
+ it "should return the role mask of an array of roles" do
389
+ subject.class.mask_for(:foo, :bar).should == 3
390
+ subject.class.mask_for(:foo, :third).should == 5
391
+ subject.class.mask_for(:foo, :bar, :third).should == 7
392
+ end
393
+
394
+ it "should return the role mask of a string array of roles" do
395
+ subject.class.mask_for("foo").should == 1
396
+ subject.class.mask_for("foo", "bar").should == 3
397
+ subject.class.mask_for("foo", "third").should == 5
398
+ end
399
+
400
+ it "should return the role mask of the existing roles" do
401
+ subject.class.mask_for(:foo, :quux).should == 1
402
+ end
403
+
404
+ it "should return 0 when a role that does not exist is passed" do
405
+ subject.class.mask_for(:quux).should == 0
406
+ end
407
+ end
408
+ end
409
+
349
410
  end
data/spec/roles_spec.rb CHANGED
@@ -5,6 +5,9 @@ describe RoleModel::Roles do
5
5
  let(:model_instance) { Class.new.new }
6
6
  let(:array) { [:foo, :bar] }
7
7
  subject { RoleModel::Roles.new(model_instance, array) }
8
+ before(:each) do
9
+ model_instance.stub(:roles=)
10
+ end
8
11
 
9
12
  its(:model_instance) { should equal(model_instance) }
10
13
  it { should include(:foo, :bar) }
@@ -16,4 +19,34 @@ describe RoleModel::Roles do
16
19
  subject << :baz
17
20
  end
18
21
  end
22
+
23
+ describe "#add" do
24
+ it "should add the given element to the model_instance.roles by re-assigning all roles" do
25
+ model_instance.should_receive(:roles=).with(array_including(:foo, :bar, :baz))
26
+ subject.add(:baz)
27
+ end
28
+ end
29
+
30
+ describe "#merge" do
31
+ it "should add the given enum to the model_instance.roles by re-assigning all roles" do
32
+ model_instance.should_receive(:roles=).with(array_including(:foo, :bar, :baz, :quux))
33
+ subject.merge([:baz, :quux])
34
+ end
35
+ end
36
+
37
+ describe "#delete" do
38
+ it "should delete the given element to the model_instance.roles by re-assigning all roles" do
39
+ model_instance.should_receive(:roles=).with(subject)
40
+ subject.delete :foo
41
+ subject.should_not include(:foo)
42
+ end
43
+ end
44
+
45
+ describe "#subtract" do
46
+ it "should remove the given enum to the model_instance.roles by re-assigning all roles" do
47
+ model_instance.should_receive(:roles=).with(subject)
48
+ subject.subtract([:foo, :bar])
49
+ subject.should have(0).roles
50
+ end
51
+ end
19
52
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: role_model
3
3
  version: !ruby/object:Gem::Version
4
- hash: 11
4
+ hash: 7
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
- - 5
8
+ - 6
9
9
  - 0
10
- version: 0.5.0
10
+ version: 0.6.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Martin Rehfeld
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2010-08-17 00:00:00 +02:00
18
+ date: 2010-10-10 00:00:00 +02:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency