roleful 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -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