role_model 0.3.1 → 0.3.2
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.
- data/README.rdoc +6 -8
- data/Rakefile +3 -0
- data/VERSION +1 -1
- data/lib/role_model/class_methods.rb +32 -0
- data/lib/role_model/implementation.rb +21 -0
- data/lib/role_model/roles.rb +1 -1
- data/lib/role_model.rb +5 -43
- data/role_model.gemspec +8 -4
- data/spec/custom_matchers.rb +2 -1
- data/spec/custom_matchers_spec.rb +62 -0
- data/spec/role_model_spec.rb +1 -1
- metadata +15 -4
data/README.rdoc
CHANGED
@@ -1,17 +1,17 @@
|
|
1
1
|
= RoleModel
|
2
2
|
|
3
|
-
|
4
|
-
|
3
|
+
RoleModel is the framework agnostic, efficient and declarative way to do
|
4
|
+
(user) roles. Assigned roles will be efficiently stored as a bitmask
|
5
|
+
directly into your model within an configurable attribute.
|
5
6
|
|
6
|
-
|
7
|
-
(default: <tt>roles_mask</tt>). Here's how to get started:
|
7
|
+
It works like this:
|
8
8
|
|
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
|
-
attr_accessor :roles_mask # in real life this would be an persisted attribute
|
14
|
+
attr_accessor :roles_mask # in real life this would be an persisted attribute
|
15
15
|
|
16
16
|
include RoleModel
|
17
17
|
|
@@ -39,7 +39,7 @@ Assigned roles will be stored as a bitmask in an configurable attribute
|
|
39
39
|
>> u.roles << :manager
|
40
40
|
=> [:admin, :manager]
|
41
41
|
|
42
|
-
#
|
42
|
+
# querying roles...
|
43
43
|
|
44
44
|
# ... retrieve all assigned roles
|
45
45
|
>> u.roles # aliased to role_symbols for DeclarativeAuthorization
|
@@ -48,8 +48,6 @@ Assigned roles will be stored as a bitmask in an configurable attribute
|
|
48
48
|
# ... check for individual roles
|
49
49
|
>> u.has_role? :author
|
50
50
|
=> false
|
51
|
-
>> u.is_a? :admin # has_role? is aliased as is_a?
|
52
|
-
=> true
|
53
51
|
|
54
52
|
# see the internal bitmask representation (3 = 0b0011)
|
55
53
|
>> u.roles_mask
|
data/Rakefile
CHANGED
@@ -28,6 +28,9 @@ Spec::Rake::SpecTask.new(:rcov) do |spec|
|
|
28
28
|
spec.libs << 'lib' << 'spec'
|
29
29
|
spec.pattern = 'spec/**/*_spec.rb'
|
30
30
|
spec.rcov = true
|
31
|
+
spec.rcov_opts.concat ['--exclude', 'rcov.rb']
|
32
|
+
spec.rcov_opts.concat ['--exclude', '.*_spec.rb']
|
33
|
+
spec.rcov_opts.concat ['--exclude', 'spec_helper.rb']
|
31
34
|
end
|
32
35
|
|
33
36
|
task :spec => :check_dependencies
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.3.
|
1
|
+
0.3.2
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module RoleModel
|
2
|
+
module ClassMethods
|
3
|
+
def inherited(subclass) # :nodoc:
|
4
|
+
::RoleModel::INHERITABLE_CLASS_ATTRIBUTES.each do |attribute|
|
5
|
+
instance_var = "@#{attribute}"
|
6
|
+
subclass.instance_variable_set(instance_var, instance_variable_get(instance_var))
|
7
|
+
end
|
8
|
+
super
|
9
|
+
end
|
10
|
+
|
11
|
+
# set the bitmask attribute role assignments will be stored in
|
12
|
+
def roles_attribute(name)
|
13
|
+
self.roles_attribute = name
|
14
|
+
end
|
15
|
+
|
16
|
+
# alternative method signature: set the bitmask attribute role assignments will be stored in
|
17
|
+
def roles_attribute=(name)
|
18
|
+
self.roles_attribute_name = name.to_sym
|
19
|
+
end
|
20
|
+
|
21
|
+
# :call-seq:
|
22
|
+
# roles(:role_1, ..., :role_n)
|
23
|
+
# roles('role_1', ..., 'role_n')
|
24
|
+
# roles([:role_1, ..., :role_n])
|
25
|
+
# roles(['role_1', ..., 'role_n'])
|
26
|
+
#
|
27
|
+
# declare valid roles
|
28
|
+
def roles(*roles)
|
29
|
+
self.valid_roles = Array[*roles].flatten.map { |r| r.to_sym }
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module RoleModel
|
2
|
+
module Implementation
|
3
|
+
|
4
|
+
# assign roles
|
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 })
|
7
|
+
end
|
8
|
+
|
9
|
+
# query assigned roles
|
10
|
+
def roles
|
11
|
+
Roles.new(self, self.class.valid_roles.reject { |r| ((self.send(self.class.roles_attribute_name) || 0) & 2**self.class.valid_roles.index(r)).zero? })
|
12
|
+
end
|
13
|
+
alias role_symbols roles
|
14
|
+
|
15
|
+
# check if a given role has been assigned
|
16
|
+
def has_role?(role)
|
17
|
+
roles.include?(role.to_sym)
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
end
|
data/lib/role_model/roles.rb
CHANGED
data/lib/role_model.rb
CHANGED
@@ -1,58 +1,20 @@
|
|
1
|
+
require 'role_model/implementation'
|
2
|
+
require 'role_model/class_methods'
|
1
3
|
require 'role_model/roles'
|
2
4
|
|
3
5
|
module RoleModel
|
4
6
|
|
5
7
|
INHERITABLE_CLASS_ATTRIBUTES = [:roles_attribute_name, :valid_roles]
|
6
8
|
|
9
|
+
include Implementation
|
10
|
+
|
7
11
|
def self.included(base) # :nodoc:
|
8
12
|
base.extend ClassMethods
|
9
13
|
base.class_eval do
|
10
14
|
class << self
|
11
15
|
attr_accessor(*::RoleModel::INHERITABLE_CLASS_ATTRIBUTES)
|
12
16
|
end
|
13
|
-
roles_attribute :roles_mask
|
14
|
-
end
|
15
|
-
|
16
|
-
# assign roles
|
17
|
-
def roles=(*roles)
|
18
|
-
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 })
|
19
|
-
end
|
20
|
-
|
21
|
-
# query assigned roles
|
22
|
-
def roles
|
23
|
-
Roles.new(self, self.class.valid_roles.reject { |r| ((self.send(self.class.roles_attribute_name) || 0) & 2**self.class.valid_roles.index(r)).zero? })
|
24
|
-
end
|
25
|
-
alias role_symbols roles
|
26
|
-
|
27
|
-
# check if a given role has been assigned
|
28
|
-
def has_role?(role)
|
29
|
-
roles.include?(role.to_sym)
|
30
|
-
end
|
31
|
-
alias is_a? has_role?
|
32
|
-
end
|
33
|
-
|
34
|
-
module ClassMethods
|
35
|
-
def inherited(subclass) # :nodoc:
|
36
|
-
::RoleModel::INHERITABLE_CLASS_ATTRIBUTES.each do |attribute|
|
37
|
-
instance_var = "@#{attribute}"
|
38
|
-
subclass.instance_variable_set(instance_var, instance_variable_get(instance_var))
|
39
|
-
end
|
40
|
-
super
|
41
|
-
end
|
42
|
-
|
43
|
-
# set the bitmask attribute role assignment will be stored in
|
44
|
-
def roles_attribute(name)
|
45
|
-
self.roles_attribute = name
|
46
|
-
end
|
47
|
-
|
48
|
-
# alternative method signature: set the bitmask attribute role assignment will be stored in
|
49
|
-
def roles_attribute=(name)
|
50
|
-
self.roles_attribute_name = name.to_sym
|
51
|
-
end
|
52
|
-
|
53
|
-
# declare valid roles
|
54
|
-
def roles(*roles)
|
55
|
-
self.valid_roles = Array[*roles].flatten.map { |r| r.to_sym }
|
17
|
+
roles_attribute :roles_mask # set default bitmask attribute
|
56
18
|
end
|
57
19
|
end
|
58
20
|
|
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.3.
|
8
|
+
s.version = "0.3.2"
|
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-
|
12
|
+
s.date = %q{2010-08-04}
|
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 = [
|
@@ -24,9 +24,12 @@ Gem::Specification.new do |s|
|
|
24
24
|
"Rakefile",
|
25
25
|
"VERSION",
|
26
26
|
"lib/role_model.rb",
|
27
|
+
"lib/role_model/class_methods.rb",
|
28
|
+
"lib/role_model/implementation.rb",
|
27
29
|
"lib/role_model/roles.rb",
|
28
30
|
"role_model.gemspec",
|
29
31
|
"spec/custom_matchers.rb",
|
32
|
+
"spec/custom_matchers_spec.rb",
|
30
33
|
"spec/role_model_spec.rb",
|
31
34
|
"spec/roles_spec.rb",
|
32
35
|
"spec/spec.opts",
|
@@ -35,10 +38,11 @@ Gem::Specification.new do |s|
|
|
35
38
|
s.homepage = %q{http://github.com/martinrehfeld/role_model}
|
36
39
|
s.rdoc_options = ["--charset=UTF-8"]
|
37
40
|
s.require_paths = ["lib"]
|
38
|
-
s.rubygems_version = %q{1.3.
|
41
|
+
s.rubygems_version = %q{1.3.7}
|
39
42
|
s.summary = %q{Declare, assign and query roles with ease}
|
40
43
|
s.test_files = [
|
41
44
|
"spec/custom_matchers.rb",
|
45
|
+
"spec/custom_matchers_spec.rb",
|
42
46
|
"spec/role_model_spec.rb",
|
43
47
|
"spec/roles_spec.rb",
|
44
48
|
"spec/spec_helper.rb"
|
@@ -48,7 +52,7 @@ Gem::Specification.new do |s|
|
|
48
52
|
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
49
53
|
s.specification_version = 3
|
50
54
|
|
51
|
-
if Gem::Version.new(Gem::
|
55
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
52
56
|
s.add_development_dependency(%q<rspec>, [">= 1.2.9"])
|
53
57
|
else
|
54
58
|
s.add_dependency(%q<rspec>, [">= 1.2.9"])
|
data/spec/custom_matchers.rb
CHANGED
@@ -5,8 +5,9 @@ module CustomMatchers
|
|
5
5
|
end
|
6
6
|
|
7
7
|
def ==(actual)
|
8
|
+
return false if actual.size < @expected.size
|
8
9
|
@expected.each do | value |
|
9
|
-
return false unless actual.
|
10
|
+
return false unless actual.any? { |actual_value| value == actual_value }
|
10
11
|
end
|
11
12
|
true
|
12
13
|
rescue NoMethodError => ex
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module CustomMatchers
|
4
|
+
describe ArrayIncludingMatcher do
|
5
|
+
|
6
|
+
it "should describe itself properly" do
|
7
|
+
ArrayIncludingMatcher.new(:a, :b).description.should == "array_including(:a, :b)"
|
8
|
+
end
|
9
|
+
|
10
|
+
describe "passing" do
|
11
|
+
it "should match the same array" do
|
12
|
+
array_including(:a).should == [:a]
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should match a array with extra stuff" do
|
16
|
+
array_including(:a).should == [:a, :b]
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should match a array regardless of element position" do
|
20
|
+
array_including(:a, :b).should == [:b, :a]
|
21
|
+
end
|
22
|
+
|
23
|
+
describe "when matching against other matchers" do
|
24
|
+
it "should match a symbol against anything()" do
|
25
|
+
array_including(anything, :b).should == [:a, :b]
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should match an int against anything()" do
|
29
|
+
array_including(anything, :b).should == [1, :b]
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should match a string against anything()" do
|
33
|
+
array_including(anything, :b).should == ["1", :b]
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should match an arbitrary object against anything()" do
|
37
|
+
array_including(anything, :b).should == [Class.new.new, :b]
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
describe "failing" do
|
43
|
+
it "should not match a non-array" do
|
44
|
+
array_including(:a).should_not == :a
|
45
|
+
end
|
46
|
+
|
47
|
+
it "should not match a array with a missing element" do
|
48
|
+
array_including(:a).should_not == [:b]
|
49
|
+
end
|
50
|
+
|
51
|
+
it "should not match an empty array with a given key" do
|
52
|
+
array_including(:a).should_not == []
|
53
|
+
end
|
54
|
+
|
55
|
+
describe "when matching against other matchers" do
|
56
|
+
it "should not match without additional elements" do
|
57
|
+
array_including(anything, 1).should_not == [1]
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
data/spec/role_model_spec.rb
CHANGED
metadata
CHANGED
@@ -1,12 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: role_model
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
+
hash: 23
|
4
5
|
prerelease: false
|
5
6
|
segments:
|
6
7
|
- 0
|
7
8
|
- 3
|
8
|
-
-
|
9
|
-
version: 0.3.
|
9
|
+
- 2
|
10
|
+
version: 0.3.2
|
10
11
|
platform: ruby
|
11
12
|
authors:
|
12
13
|
- Martin Rehfeld
|
@@ -14,16 +15,18 @@ autorequire:
|
|
14
15
|
bindir: bin
|
15
16
|
cert_chain: []
|
16
17
|
|
17
|
-
date: 2010-
|
18
|
+
date: 2010-08-04 00:00:00 +02:00
|
18
19
|
default_executable:
|
19
20
|
dependencies:
|
20
21
|
- !ruby/object:Gem::Dependency
|
21
22
|
name: rspec
|
22
23
|
prerelease: false
|
23
24
|
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
24
26
|
requirements:
|
25
27
|
- - ">="
|
26
28
|
- !ruby/object:Gem::Version
|
29
|
+
hash: 13
|
27
30
|
segments:
|
28
31
|
- 1
|
29
32
|
- 2
|
@@ -48,9 +51,12 @@ files:
|
|
48
51
|
- Rakefile
|
49
52
|
- VERSION
|
50
53
|
- lib/role_model.rb
|
54
|
+
- lib/role_model/class_methods.rb
|
55
|
+
- lib/role_model/implementation.rb
|
51
56
|
- lib/role_model/roles.rb
|
52
57
|
- role_model.gemspec
|
53
58
|
- spec/custom_matchers.rb
|
59
|
+
- spec/custom_matchers_spec.rb
|
54
60
|
- spec/role_model_spec.rb
|
55
61
|
- spec/roles_spec.rb
|
56
62
|
- spec/spec.opts
|
@@ -65,28 +71,33 @@ rdoc_options:
|
|
65
71
|
require_paths:
|
66
72
|
- lib
|
67
73
|
required_ruby_version: !ruby/object:Gem::Requirement
|
74
|
+
none: false
|
68
75
|
requirements:
|
69
76
|
- - ">="
|
70
77
|
- !ruby/object:Gem::Version
|
78
|
+
hash: 3
|
71
79
|
segments:
|
72
80
|
- 0
|
73
81
|
version: "0"
|
74
82
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
83
|
+
none: false
|
75
84
|
requirements:
|
76
85
|
- - ">="
|
77
86
|
- !ruby/object:Gem::Version
|
87
|
+
hash: 3
|
78
88
|
segments:
|
79
89
|
- 0
|
80
90
|
version: "0"
|
81
91
|
requirements: []
|
82
92
|
|
83
93
|
rubyforge_project:
|
84
|
-
rubygems_version: 1.3.
|
94
|
+
rubygems_version: 1.3.7
|
85
95
|
signing_key:
|
86
96
|
specification_version: 3
|
87
97
|
summary: Declare, assign and query roles with ease
|
88
98
|
test_files:
|
89
99
|
- spec/custom_matchers.rb
|
100
|
+
- spec/custom_matchers_spec.rb
|
90
101
|
- spec/role_model_spec.rb
|
91
102
|
- spec/roles_spec.rb
|
92
103
|
- spec/spec_helper.rb
|