roleful 0.0.2 → 0.0.3

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.
@@ -0,0 +1,5 @@
1
+ class Array
2
+ def extract_options!
3
+ last.is_a?(Hash) ? pop : { }
4
+ end
5
+ end
@@ -0,0 +1,21 @@
1
+ # http://eigenclass.org/hiki/bounded+space+instance_exec
2
+ class Object
3
+ module InstanceExecHelper; end
4
+ include InstanceExecHelper
5
+ def instance_exec(*args, &block)
6
+ begin
7
+ old_critical, Thread.critical = Thread.critical, true
8
+ n = 0
9
+ n += 1 while respond_to?(mname="__instance_exec#{n}")
10
+ InstanceExecHelper.module_eval{ define_method(mname, &block) }
11
+ ensure
12
+ Thread.critical = old_critical
13
+ end
14
+ begin
15
+ ret = send(mname, *args)
16
+ ensure
17
+ InstanceExecHelper.module_eval{ remove_method(mname) } rescue nil
18
+ end
19
+ ret
20
+ end
21
+ end
data/lib/roleful.rb CHANGED
@@ -1,11 +1,19 @@
1
1
  $LOAD_PATH << File.dirname(__FILE__) + '/roleful'
2
+ $LOAD_PATH << File.dirname(__FILE__) + '/core_ext'
2
3
 
3
- require 'rubygems'
4
- require 'nakajima'
5
- require 'set'
4
+ # Core extensions
5
+ require 'object' unless respond_to?(:instance_exec)
6
+ require 'array' unless [].respond_to?(:extract_options!)
7
+
8
+ # Project files
6
9
  require 'role'
7
10
  require 'inclusion'
8
11
 
12
+ # Other libraries
13
+ require 'rubygems'
14
+ require 'metaid'
15
+ require 'set'
16
+
9
17
  module Roleful
10
- VERSION = '0.0.2'
18
+ VERSION = '0.0.3'
11
19
  end
@@ -10,10 +10,12 @@ module Roleful
10
10
  end
11
11
 
12
12
  module InstanceMethods
13
+ # Gives an object temporary roles for the duration of the block.
13
14
  def with_role(*tmp_roles)
14
- old = meta_def(:role) {tmp_roles }
15
+ old_role = method(:role)
16
+ meta_def(:role) { tmp_roles }
15
17
  result = yield
16
- meta_eval { remove_method(:role) }
18
+ meta_eval { define_method(:role, old_role) }
17
19
  result
18
20
  end
19
21
 
@@ -44,9 +46,10 @@ module Roleful
44
46
  roles.each { |name| define_role(name.to_sym, options, &block) }
45
47
  end
46
48
 
47
- # Adapted from ActiveSupport, modified a bit to ease binding contexts
49
+ # Delegates method calls to the object's #role_proxy, accounting for
50
+ # cases when there are multiple roles for the given object.
48
51
  def delegate_permission(*methods)
49
- options = methods.pop
52
+ options = methods.pop
50
53
  raise ArgumentError, "Delegation needs a target." unless options.is_a?(Hash) && to = options[:to]
51
54
 
52
55
  methods.each do |method|
data/lib/roleful/role.rb CHANGED
@@ -9,22 +9,20 @@ module Roleful
9
9
  define_predicates
10
10
  end
11
11
 
12
- def can(permission, &block)
13
- permission_name = "can_#{permission}?"
12
+ def can(sym, &block)
13
+ handlers[sym] = block || proc { true }
14
14
 
15
- handlers[permission] = block || proc { true }
16
- meta_def(permission_name) { |target, *args| handle(target, permission, *args) }
17
-
18
- meta_delegate(permission_name)
19
- add_permission(permission)
20
- end
21
-
22
- def can?(target, permission, *args)
23
- superuser? ?
24
- @klass::PERMISSIONS.include?(permission) :
25
- handle(target, permission, *args)
15
+ metaclass.class_eval(<<-END, __FILE__, __LINE__)
16
+ def can_#{sym}?(target, *args)
17
+ handle(target, #{sym.inspect}, *args)
18
+ end
19
+ END
20
+
21
+ register_permission(sym)
26
22
  end
27
23
 
24
+ # Used when the permission in question is granted for the
25
+ # role in question. TODO: Is this really necessary?
28
26
  def method_missing(sym, *args)
29
27
  method_id = sym.to_s
30
28
  match_permission_or_predicate?(method_id) ? superuser? : super
@@ -32,6 +30,12 @@ module Roleful
32
30
 
33
31
  private
34
32
 
33
+ def can?(target, permission, *args)
34
+ superuser? ?
35
+ @klass::PERMISSIONS.include?(permission) :
36
+ handle(target, permission, *args)
37
+ end
38
+
35
39
  def handle(target, permission, *args)
36
40
  return false if handlers[permission].nil?
37
41
  target.instance_exec(*args, &handlers[permission])
@@ -41,10 +45,12 @@ module Roleful
41
45
  options[:superuser] || false # returns false, not nil
42
46
  end
43
47
 
48
+ # TODO memoize the generated regex
44
49
  def permission?(method)
45
50
  method.match(/can_(#{@klass::PERMISSIONS.to_a.join('|')})+\?/)
46
51
  end
47
52
 
53
+ # TODO memoize the generated regex
48
54
  def predicate?(method)
49
55
  method.match(/(#{@klass::ROLES.keys.join('|')})\?/)
50
56
  end
@@ -55,17 +61,18 @@ module Roleful
55
61
 
56
62
  def define_predicates
57
63
  meta_def("#{name}?") { true }
58
- meta_delegate("#{name}?")
59
- meta_delegate("can?")
64
+ delegate_predicate("#{name}?")
65
+ delegate_predicate("can?")
60
66
  end
61
67
 
62
- def add_permission(permission)
68
+ def register_permission(permission)
63
69
  permission = permission.to_sym
64
70
  @permissions.add(permission)
65
71
  @klass::PERMISSIONS.merge(@permissions)
72
+ delegate_predicate("can_#{permission}?")
66
73
  end
67
74
 
68
- def meta_delegate(name)
75
+ def delegate_predicate(name)
69
76
  @klass.delegate_permission name, :to => :role_proxy
70
77
  end
71
78
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: roleful
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Pat Nakajima
@@ -22,16 +22,6 @@ dependencies:
22
22
  - !ruby/object:Gem::Version
23
23
  version: "0"
24
24
  version:
25
- - !ruby/object:Gem::Dependency
26
- name: nakajima-nakajima
27
- type: :runtime
28
- version_requirement:
29
- version_requirements: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - ">="
32
- - !ruby/object:Gem::Version
33
- version: "0"
34
- version:
35
25
  description:
36
26
  email: patnakajima@gmail.com
37
27
  executables: []
@@ -41,6 +31,9 @@ extensions: []
41
31
  extra_rdoc_files: []
42
32
 
43
33
  files:
34
+ - lib/core_ext
35
+ - lib/core_ext/array.rb
36
+ - lib/core_ext/object.rb
44
37
  - lib/roleful
45
38
  - lib/roleful/inclusion.rb
46
39
  - lib/roleful/role.rb
@@ -67,7 +60,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
67
60
  requirements: []
68
61
 
69
62
  rubyforge_project:
70
- rubygems_version: 1.3.0
63
+ rubygems_version: 1.3.1
71
64
  signing_key:
72
65
  specification_version: 2
73
66
  summary: Generic roles for you and your objects