be9-acl9 0.9.1 → 0.9.2
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.textile +9 -0
- data/Manifest +14 -11
- data/README.textile +59 -22
- data/acl9.gemspec +4 -4
- data/lib/acl9/controller_extensions.rb +37 -13
- data/lib/acl9/controller_extensions/dsl_base.rb +212 -0
- data/lib/acl9/controller_extensions/generators.rb +119 -0
- data/lib/acl9/version.rb +1 -1
- data/spec/access_control_spec.rb +87 -13
- data/spec/dsl_base_spec.rb +703 -0
- data/spec/roles_spec.rb +1 -0
- metadata +22 -18
- data/lib/acl9/controller_extensions/filter_producer.rb +0 -244
- data/spec/filter_producer_spec.rb +0 -707
data/CHANGELOG.textile
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
h2. 0.9.2 (11-Jan-2009)
|
2
|
+
|
3
|
+
* @access_control :method do end@ as shorter form for @access_control :as_method => :method do end@.
|
4
|
+
* Boolean method can now receive an objects hash which will be looked into first before taking
|
5
|
+
an instance variable.
|
6
|
+
|
7
|
+
h2. 0.9.1 (03-Jan-2009)
|
8
|
+
|
9
|
+
Initial release.
|
data/Manifest
CHANGED
@@ -1,19 +1,22 @@
|
|
1
|
-
|
1
|
+
init.rb
|
2
|
+
Manifest
|
3
|
+
lib/acl9/model_extensions.rb
|
4
|
+
lib/acl9/version.rb
|
2
5
|
lib/acl9/model_extensions/subject.rb
|
3
6
|
lib/acl9/model_extensions/object.rb
|
7
|
+
lib/acl9/controller_extensions/generators.rb
|
8
|
+
lib/acl9/controller_extensions/dsl_base.rb
|
9
|
+
lib/acl9/config.rb
|
4
10
|
lib/acl9/controller_extensions.rb
|
5
|
-
lib/acl9/controller_extensions/filter_producer.rb
|
6
|
-
lib/acl9/version.rb
|
7
|
-
lib/acl9/model_extensions.rb
|
8
11
|
lib/acl9.rb
|
12
|
+
README.textile
|
13
|
+
acl9.gemspec
|
14
|
+
CHANGELOG.textile
|
15
|
+
MIT-LICENSE
|
16
|
+
Rakefile
|
9
17
|
spec/db/schema.rb
|
10
|
-
spec/
|
18
|
+
spec/dsl_base_spec.rb
|
11
19
|
spec/spec_helper.rb
|
12
|
-
spec/models.rb
|
13
20
|
spec/access_control_spec.rb
|
14
21
|
spec/roles_spec.rb
|
15
|
-
|
16
|
-
MIT-LICENSE
|
17
|
-
Rakefile
|
18
|
-
README.textile
|
19
|
-
init.rb
|
22
|
+
spec/models.rb
|
data/README.textile
CHANGED
@@ -45,7 +45,7 @@ Acl9 can be installed as a gem from "GitHub":http://github.com.
|
|
45
45
|
Add the following line to your @config/environment.rb@:
|
46
46
|
|
47
47
|
<pre><code>
|
48
|
-
config.gem "be9-acl9", :source => "http://gems.github.com"
|
48
|
+
config.gem "be9-acl9", :source => "http://gems.github.com", :lib => "acl9"
|
49
49
|
</pre></code>
|
50
50
|
|
51
51
|
Then run @rake gems:install@ (with possible @rake gems:unpack@ thereafter) and you're done!
|
@@ -118,7 +118,7 @@ Role control subsystem has been lifted from
|
|
118
118
|
but undergone some modifications.
|
119
119
|
|
120
120
|
It's based on two tables in the database. First, role table, which stores pairs @[role_name, object]@
|
121
|
-
where object is a polymorphic
|
121
|
+
where object is a polymorphic model instance or a class. Second, join table, which joins users and roles.
|
122
122
|
|
123
123
|
To use this subsystem, you should define a @Role@ model.
|
124
124
|
|
@@ -142,7 +142,7 @@ The structure of @roles@ table is as follows:
|
|
142
142
|
end
|
143
143
|
</code></pre>
|
144
144
|
|
145
|
-
Note that you will never use the @Role@ class directly.
|
145
|
+
Note that you will almost never use the @Role@ class directly.
|
146
146
|
|
147
147
|
h2. Subject model
|
148
148
|
|
@@ -333,7 +333,7 @@ In other words, you are _manager_ if you manage at least one @foo@ (or a @bar@..
|
|
333
333
|
user.has_role? :manager # => true
|
334
334
|
</code></pre>
|
335
335
|
|
336
|
-
Our @user@ is no more manager of @foo@, but
|
336
|
+
Our @user@ is no more manager of @foo@, but has become a manager of @bar@.
|
337
337
|
|
338
338
|
<pre><code>
|
339
339
|
user.has_no_roles!
|
@@ -343,7 +343,7 @@ Our @user@ is no more manager of @foo@, but is now a manager of @bar@.
|
|
343
343
|
user.roles # => []
|
344
344
|
</code></pre>
|
345
345
|
|
346
|
-
|
346
|
+
At this time @user@ has no roles in the system.
|
347
347
|
|
348
348
|
h2. Coming up with your own role implementation
|
349
349
|
|
@@ -381,7 +381,7 @@ from unauthorized access. Acl9 provides a nice DSL for writing access rules.
|
|
381
381
|
|
382
382
|
h2. Allow and deny
|
383
383
|
|
384
|
-
Access control is mostly about allowing and denying. So there two
|
384
|
+
Access control is mostly about allowing and denying. So there are two
|
385
385
|
basic methods: @allow@ and @deny@. They have the same syntax:
|
386
386
|
|
387
387
|
<pre><code>
|
@@ -397,8 +397,8 @@ ROLE_LIST is a list of roles (at least 1 role should be there). So,
|
|
397
397
|
allow :manager, :admin
|
398
398
|
deny :banned
|
399
399
|
</code></pre>
|
400
|
-
will match holders of global role _manager_ *and* holders of global role _admin_ as allowed
|
401
|
-
_banned_ as denied.
|
400
|
+
will match holders of global role _manager_ *and* holders of global role _admin_ as allowed.
|
401
|
+
On the contrary, holders of _banned_ role will match as denied.
|
402
402
|
|
403
403
|
Basically this snippet is equivalent to
|
404
404
|
|
@@ -407,13 +407,13 @@ Basically this snippet is equivalent to
|
|
407
407
|
allow :admin
|
408
408
|
deny :banned
|
409
409
|
</code></pre>
|
410
|
-
which means that roles in argument list
|
410
|
+
which means that roles in argument list are OR'ed for a match, and not AND'ed.
|
411
411
|
|
412
412
|
Also note that:
|
413
413
|
* You may use both strings and :symbols to specify roles (the latter get converted into strings).
|
414
414
|
* Role names are singularized before check.
|
415
415
|
|
416
|
-
|
416
|
+
Thus the snippet above can also be written as
|
417
417
|
|
418
418
|
<pre><code>
|
419
419
|
allow :managers, :admins
|
@@ -440,7 +440,7 @@ use object and class roles in the ACL block.
|
|
440
440
|
deny :hated, :by => :us
|
441
441
|
</code></pre>
|
442
442
|
|
443
|
-
|
443
|
+
To specify an object you use one of the 6 preposition options:
|
444
444
|
* :of
|
445
445
|
* :at
|
446
446
|
* :on
|
@@ -482,8 +482,6 @@ Checking against an instance variable has sense when you have another _before fi
|
|
482
482
|
end
|
483
483
|
</code></pre>
|
484
484
|
|
485
|
-
|
486
|
-
|
487
485
|
Note that the object option is applied to all of the roles you specify in the argument list.
|
488
486
|
As such,
|
489
487
|
|
@@ -589,7 +587,7 @@ Same result as a table:
|
|
589
587
|
| None of the @allow@ rules matched, some of the @deny@ rules matched. | Access is denied. | Access is denied. |
|
590
588
|
| Some of the @allow@ rules matched, some of the @deny@ rules matched. | Access is allowed. | Access is denied. |
|
591
589
|
|
592
|
-
Apparently _default deny_ mode is
|
590
|
+
Apparently _default deny_ mode is more strict, and that's because it's on by default.
|
593
591
|
|
594
592
|
h2. Actions block
|
595
593
|
|
@@ -644,11 +642,12 @@ By calling @access_control@ in your controller you can get your ACL block transl
|
|
644
642
|
First case is by default. You can catch the exception with @rescue_from@ call and do something
|
645
643
|
you like: make a redirect, or render "Access denied" template, or whatever.
|
646
644
|
|
647
|
-
Second case is obtained with
|
648
|
-
|
645
|
+
Second case is obtained with specifying method name as an argument to
|
646
|
+
@access_control@ (or using @:as_method@ option, see below) and may be helpful
|
647
|
+
if you want to use @skip_before_filter@ somewhere in the derived controller.
|
649
648
|
|
650
|
-
Third case will take place if you
|
651
|
-
method which you can call anywhere you want.
|
649
|
+
Third case will take place if you supply @:filter => false@ along with method
|
650
|
+
name. You'll get an ordinary method which you can call anywhere you want.
|
652
651
|
|
653
652
|
h3. :subject_method
|
654
653
|
|
@@ -694,14 +693,30 @@ In the case
|
|
694
693
|
|
695
694
|
access control checks will be added as @acl@ method onto MyController, with @before_filter :acl@ call thereafter.
|
696
695
|
|
696
|
+
Instead of using @:as_method@ you may specify the name of the method as a positional argument
|
697
|
+
to @access_control@:
|
698
|
+
|
699
|
+
<pre><code>
|
700
|
+
class MyController < ApplicationController
|
701
|
+
access_control :acl do
|
702
|
+
# ...
|
703
|
+
end
|
704
|
+
|
705
|
+
# ...
|
706
|
+
end
|
707
|
+
</code></pre>
|
708
|
+
|
709
|
+
|
697
710
|
h3. :filter
|
698
711
|
|
699
|
-
If you set @:filter@ to @false@ (it's @true@ by default) and also use
|
700
|
-
|
712
|
+
If you set @:filter@ to @false@ (it's @true@ by default) and also use
|
713
|
+
@:as_method@ (or method name as 1st argument to @access_control@, you'll get a
|
714
|
+
method which won't raise @Acl9::AccessDenied@ exception, but rather return
|
715
|
+
@true@ or @false@ (access allowed/denied).
|
701
716
|
|
702
717
|
<pre><code>
|
703
718
|
class SecretController < ApplicationController
|
704
|
-
access_control :
|
719
|
+
access_control :secret_access?, :filter => false do
|
705
720
|
allow :james_bond
|
706
721
|
# ...
|
707
722
|
end
|
@@ -728,6 +743,26 @@ which won't raise @Acl9::AccessDenied@ exception, but rather return @true@ or @f
|
|
728
743
|
end
|
729
744
|
</code></pre>
|
730
745
|
|
746
|
+
The generated method can receive an objects hash as an argument. In this example,
|
747
|
+
|
748
|
+
<pre><code>
|
749
|
+
class LolController < ApplicationController
|
750
|
+
access_control :lolcats?, :filter => false do
|
751
|
+
allow :cats, :by => :lol
|
752
|
+
# ...
|
753
|
+
end
|
754
|
+
end
|
755
|
+
</code></pre>
|
756
|
+
|
757
|
+
you may not only call @lolcats?@ with no arguments, which will basically return
|
758
|
+
|
759
|
+
<pre><code>
|
760
|
+
current_user.has_role?('cats', @lol)
|
761
|
+
</code></pre>
|
762
|
+
|
763
|
+
but also as @lolcats?(:lol => Lol.find(params[:lol]))@. The hash will be looked into first,
|
764
|
+
even if you have an instance variable @lol@.
|
765
|
+
|
731
766
|
h3. Other options
|
732
767
|
|
733
768
|
Other options will be passed to @before_filter@. As such, you may use @:only@ and @:except@ to narrow
|
@@ -762,4 +797,6 @@ is basically equivalent to
|
|
762
797
|
</code></pre>
|
763
798
|
|
764
799
|
|
765
|
-
Copyright (c) 2009 Oleg Dashevskii, released under the MIT license
|
800
|
+
Copyright (c) 2009 Oleg Dashevskii, released under the MIT license.
|
801
|
+
|
802
|
+
Contact me at "#{%w(Oleg Dashevskii).join('').downcase}@gmail.com"
|
data/acl9.gemspec
CHANGED
@@ -2,15 +2,15 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = %q{acl9}
|
5
|
-
s.version = "0.9.
|
5
|
+
s.version = "0.9.2"
|
6
6
|
|
7
7
|
s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
|
8
8
|
s.authors = ["Oleg Dashevskii"]
|
9
|
-
s.date = %q{2009-01-
|
9
|
+
s.date = %q{2009-01-14}
|
10
10
|
s.description = %q{Yet another role-based authorization system for Rails with a nice DSL for access control lists.}
|
11
11
|
s.email = %q{olegdashevskii@gmail.com}
|
12
|
-
s.extra_rdoc_files = ["lib/acl9/
|
13
|
-
s.files = ["lib/acl9/
|
12
|
+
s.extra_rdoc_files = ["lib/acl9/model_extensions.rb", "lib/acl9/version.rb", "lib/acl9/model_extensions/subject.rb", "lib/acl9/model_extensions/object.rb", "lib/acl9/controller_extensions/generators.rb", "lib/acl9/controller_extensions/dsl_base.rb", "lib/acl9/config.rb", "lib/acl9/controller_extensions.rb", "lib/acl9.rb", "README.textile", "CHANGELOG.textile"]
|
13
|
+
s.files = ["init.rb", "Manifest", "lib/acl9/model_extensions.rb", "lib/acl9/version.rb", "lib/acl9/model_extensions/subject.rb", "lib/acl9/model_extensions/object.rb", "lib/acl9/controller_extensions/generators.rb", "lib/acl9/controller_extensions/dsl_base.rb", "lib/acl9/config.rb", "lib/acl9/controller_extensions.rb", "lib/acl9.rb", "README.textile", "acl9.gemspec", "CHANGELOG.textile", "MIT-LICENSE", "Rakefile", "spec/db/schema.rb", "spec/dsl_base_spec.rb", "spec/spec_helper.rb", "spec/access_control_spec.rb", "spec/roles_spec.rb", "spec/models.rb"]
|
14
14
|
s.has_rdoc = true
|
15
15
|
s.homepage = %q{http://github.com/be9/acl9}
|
16
16
|
s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Acl9", "--main", "README.textile"]
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require File.join(File.dirname(__FILE__), 'controller_extensions', '
|
1
|
+
require File.join(File.dirname(__FILE__), 'controller_extensions', 'generators')
|
2
2
|
|
3
3
|
module Acl9
|
4
4
|
module ControllerExtensions
|
@@ -7,30 +7,54 @@ module Acl9
|
|
7
7
|
end
|
8
8
|
|
9
9
|
module ClassMethods
|
10
|
-
def access_control(
|
10
|
+
def access_control(*args, &block)
|
11
|
+
opts = if args.last.is_a? Hash
|
12
|
+
args.pop
|
13
|
+
else
|
14
|
+
{}
|
15
|
+
end
|
16
|
+
|
17
|
+
case args.size
|
18
|
+
when 0 then true
|
19
|
+
when 1
|
20
|
+
meth = args.first
|
21
|
+
|
22
|
+
if meth.is_a? Symbol
|
23
|
+
opts[:as_method] = meth
|
24
|
+
else
|
25
|
+
raise ArgumentError, "access control argument must be a :symbol!"
|
26
|
+
end
|
27
|
+
else
|
28
|
+
raise ArgumentError, "Invalid arguments for access_control"
|
29
|
+
end
|
30
|
+
|
11
31
|
subject_method = opts.delete(:subject_method) || Acl9::config[:default_subject_method]
|
12
32
|
|
13
33
|
raise ArgumentError, "Block must be supplied to access_control" unless block
|
14
34
|
|
15
|
-
producer = Acl9::FilterProducer.new(subject_method)
|
16
|
-
producer.acl(&block)
|
17
|
-
|
18
35
|
filter = opts.delete(:filter)
|
19
36
|
filter = true if filter.nil?
|
20
37
|
|
38
|
+
method = opts.delete(:as_method)
|
39
|
+
|
40
|
+
generator = case
|
41
|
+
when method && filter
|
42
|
+
Acl9::Dsl::Generators::FilterMethod.new(subject_method, method)
|
43
|
+
when method && !filter
|
44
|
+
Acl9::Dsl::Generators::BooleanMethod.new(subject_method, method)
|
45
|
+
else
|
46
|
+
Acl9::Dsl::Generators::FilterLambda.new(subject_method)
|
47
|
+
end
|
48
|
+
|
49
|
+
generator.acl_block!(&block)
|
50
|
+
|
21
51
|
if opts.delete(:debug)
|
22
52
|
Rails::logger.debug "=== Acl9 access_control expression dump (#{self.to_s})"
|
23
|
-
Rails::logger.debug
|
53
|
+
Rails::logger.debug generator.to_s
|
24
54
|
Rails::logger.debug "======"
|
25
55
|
end
|
26
56
|
|
27
|
-
|
28
|
-
class_eval producer.to_method_code(method, filter)
|
29
|
-
|
30
|
-
before_filter(method, opts) if filter
|
31
|
-
else
|
32
|
-
before_filter(opts, &producer.to_proc)
|
33
|
-
end
|
57
|
+
generator.install_on(self, opts)
|
34
58
|
end
|
35
59
|
end
|
36
60
|
end
|
@@ -0,0 +1,212 @@
|
|
1
|
+
module Acl9
|
2
|
+
module Dsl
|
3
|
+
class Base
|
4
|
+
attr_reader :allows, :denys
|
5
|
+
|
6
|
+
def initialize(*args)
|
7
|
+
@default_action = nil
|
8
|
+
|
9
|
+
@allows = []
|
10
|
+
@denys = []
|
11
|
+
|
12
|
+
@original_args = args
|
13
|
+
end
|
14
|
+
|
15
|
+
def acl_block!(&acl_block)
|
16
|
+
self.instance_eval(&acl_block)
|
17
|
+
end
|
18
|
+
|
19
|
+
def default_action
|
20
|
+
@default_action.nil? ? :deny : @default_action
|
21
|
+
end
|
22
|
+
|
23
|
+
def allowance_expression
|
24
|
+
allowed_expr = if @allows.size > 0
|
25
|
+
@allows.map { |clause| "(#{clause})" }.join(' || ')
|
26
|
+
else
|
27
|
+
"false"
|
28
|
+
end
|
29
|
+
|
30
|
+
not_denied_expr = if @denys.size > 0
|
31
|
+
@denys.map { |clause| "!(#{clause})" }.join(' && ')
|
32
|
+
else
|
33
|
+
"true"
|
34
|
+
end
|
35
|
+
|
36
|
+
[allowed_expr, not_denied_expr].
|
37
|
+
map { |expr| "(#{expr})" }.
|
38
|
+
join(default_action == :deny ? ' && ' : ' || ')
|
39
|
+
end
|
40
|
+
|
41
|
+
alias to_s allowance_expression
|
42
|
+
|
43
|
+
protected
|
44
|
+
|
45
|
+
def default(default_action)
|
46
|
+
raise ArgumentError, "default can only be called once in access_control block" if @default_action
|
47
|
+
|
48
|
+
unless [:allow, :deny].include? default_action
|
49
|
+
raise ArgumentError, "invalid value for default (can be :allow or :deny)"
|
50
|
+
end
|
51
|
+
|
52
|
+
@default_action = default_action
|
53
|
+
end
|
54
|
+
|
55
|
+
def allow(*args)
|
56
|
+
@current_rule = :allow
|
57
|
+
_parse_and_add_rule(*args)
|
58
|
+
end
|
59
|
+
|
60
|
+
def deny(*args)
|
61
|
+
@current_rule = :deny
|
62
|
+
_parse_and_add_rule(*args)
|
63
|
+
end
|
64
|
+
|
65
|
+
def actions(*args, &block)
|
66
|
+
raise ArgumentError, "actions should receive at least 1 action as argument" if args.size < 1
|
67
|
+
|
68
|
+
subsidiary = self.class.new(*@original_args)
|
69
|
+
|
70
|
+
class <<subsidiary
|
71
|
+
def actions(*args)
|
72
|
+
raise ArgumentError, "You cannot use actions inside another actions block"
|
73
|
+
end
|
74
|
+
|
75
|
+
def default(*args)
|
76
|
+
raise ArgumentError, "You cannot use default inside an actions block"
|
77
|
+
end
|
78
|
+
|
79
|
+
def _set_action_clause(to, except)
|
80
|
+
raise ArgumentError, "You cannot use :to/:except inside actions block" if to || except
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
subsidiary.acl_block!(&block)
|
85
|
+
|
86
|
+
action_check = _action_check_expression(args)
|
87
|
+
|
88
|
+
squash = lambda do |rules|
|
89
|
+
_either_of(rules) + ' && ' + action_check
|
90
|
+
end
|
91
|
+
|
92
|
+
@allows << squash.call(subsidiary.allows) if subsidiary.allows.size > 0
|
93
|
+
@denys << squash.call(subsidiary.denys) if subsidiary.denys.size > 0
|
94
|
+
end
|
95
|
+
|
96
|
+
alias action actions
|
97
|
+
|
98
|
+
def anonymous; nil end
|
99
|
+
def all; true end
|
100
|
+
def logged_in; false end
|
101
|
+
|
102
|
+
def _parse_and_add_rule(*args)
|
103
|
+
options = if args.last.is_a? Hash
|
104
|
+
args.pop
|
105
|
+
else
|
106
|
+
{}
|
107
|
+
end
|
108
|
+
|
109
|
+
_set_action_clause(options.delete(:to), options.delete(:except))
|
110
|
+
|
111
|
+
object = _role_object(options)
|
112
|
+
|
113
|
+
role_checks = args.map do |who|
|
114
|
+
case who
|
115
|
+
when nil then "#{_subject_ref}.nil?" # anonymous
|
116
|
+
when false then "!#{_subject_ref}.nil?" # logged_in
|
117
|
+
when true then "true" # all
|
118
|
+
else
|
119
|
+
"!#{_subject_ref}.nil? && #{_subject_ref}.has_role?('#{who.to_s.singularize}', #{object})"
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
_add_rule case role_checks.size
|
124
|
+
when 0
|
125
|
+
raise ArgumentError, "allow/deny should have at least 1 argument"
|
126
|
+
when 1 then role_checks.first
|
127
|
+
else
|
128
|
+
_either_of(role_checks)
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
def _either_of(exprs)
|
133
|
+
exprs.map { |expr| "(#{expr})" }.join(' || ')
|
134
|
+
end
|
135
|
+
|
136
|
+
def _add_rule(what)
|
137
|
+
what = "(#{what}) && #{@action_clause}" if @action_clause
|
138
|
+
|
139
|
+
(@current_rule == :allow ? @allows : @denys) << what
|
140
|
+
end
|
141
|
+
|
142
|
+
def _set_action_clause(to, except)
|
143
|
+
raise ArgumentError, "both :to and :except cannot be specified in the rule" if to && except
|
144
|
+
|
145
|
+
@action_clause = nil
|
146
|
+
|
147
|
+
action_list = to || except
|
148
|
+
return unless action_list
|
149
|
+
|
150
|
+
expr = _action_check_expression(action_list)
|
151
|
+
|
152
|
+
@action_clause = if to
|
153
|
+
"#{expr}"
|
154
|
+
else
|
155
|
+
"!#{expr}"
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
def _action_check_expression(action_list)
|
160
|
+
unless action_list.is_a?(Array)
|
161
|
+
action_list = [ action_list.to_s ]
|
162
|
+
end
|
163
|
+
|
164
|
+
case action_list.size
|
165
|
+
when 0 then "true"
|
166
|
+
when 1 then "(#{_action_ref} == '#{action_list.first}')"
|
167
|
+
else
|
168
|
+
set_of_actions = "Set.new([" + action_list.map { |act| "'#{act}'"}.join(',') + "])"
|
169
|
+
|
170
|
+
"#{set_of_actions}.include?(#{_action_ref})"
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
VALID_PREPOSITIONS = %w(of for in on at by).freeze unless defined? VALID_PREPOSITIONS
|
175
|
+
|
176
|
+
def _role_object(options)
|
177
|
+
object = nil
|
178
|
+
|
179
|
+
VALID_PREPOSITIONS.each do |prep|
|
180
|
+
if options[prep.to_sym]
|
181
|
+
raise ArgumentError, "You may only use one preposition to specify object" if object
|
182
|
+
|
183
|
+
object = options[prep.to_sym]
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
case object
|
188
|
+
when Class
|
189
|
+
object.to_s
|
190
|
+
when Symbol
|
191
|
+
_object_ref object
|
192
|
+
when nil
|
193
|
+
"nil"
|
194
|
+
else
|
195
|
+
raise ArgumentError, "object specified by preposition can only be a Class or a Symbol"
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
def _subject_ref
|
200
|
+
raise
|
201
|
+
end
|
202
|
+
|
203
|
+
def _object_ref(object)
|
204
|
+
raise
|
205
|
+
end
|
206
|
+
|
207
|
+
def _action_ref
|
208
|
+
raise
|
209
|
+
end
|
210
|
+
end
|
211
|
+
end
|
212
|
+
end
|