rolify 3.1.0 → 3.2.0.rc2
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/.gitignore +2 -1
- data/.travis.yml +2 -4
- data/CHANGELOG.rdoc +17 -0
- data/README.md +42 -6
- data/lib/generators/rolify/role/role_generator.rb +11 -3
- data/lib/generators/rolify/role/templates/initializer.rb +2 -1
- data/lib/generators/rolify/role/templates/role-active_record.rb +2 -0
- data/lib/generators/rolify/role/templates/role-mongoid.rb +11 -9
- data/lib/rolify.rb +13 -5
- data/lib/rolify/adapters/active_record/resource_adapter.rb +11 -4
- data/lib/rolify/adapters/active_record/role_adapter.rb +11 -4
- data/lib/rolify/adapters/active_record/scopes.rb +27 -0
- data/lib/rolify/adapters/base.rb +5 -0
- data/lib/rolify/adapters/mongoid/resource_adapter.rb +9 -5
- data/lib/rolify/adapters/mongoid/role_adapter.rb +14 -2
- data/lib/rolify/adapters/mongoid/scopes.rb +27 -0
- data/lib/rolify/finders.rb +39 -0
- data/lib/rolify/railtie.rb +1 -1
- data/lib/rolify/resource.rb +2 -1
- data/lib/rolify/role.rb +12 -2
- data/lib/rolify/version.rb +1 -1
- data/rolify.gemspec +4 -4
- data/spec/generators/rolify/role/role_generator_spec.rb +17 -61
- data/spec/rolify/custom_spec.rb +12 -0
- data/spec/rolify/resource_spec.rb +31 -0
- data/spec/rolify/role_spec.rb +12 -0
- data/spec/rolify/shared_contexts.rb +12 -0
- data/spec/rolify/shared_examples/shared_examples_for_callbacks.rb +57 -0
- data/spec/rolify/shared_examples/shared_examples_for_finders.rb +77 -0
- data/spec/rolify/shared_examples/shared_examples_for_roles.rb +39 -27
- data/spec/rolify/shared_examples/shared_examples_for_scopes.rb +38 -0
- data/spec/spec_helper.rb +13 -0
- data/spec/support/adapters/active_record.rb +4 -0
- data/spec/support/adapters/mongoid.rb +23 -3
- data/spec/support/adapters/mongoid.yml +6 -0
- metadata +82 -30
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
data/CHANGELOG.rdoc
CHANGED
@@ -1,3 +1,20 @@
|
|
1
|
+
= 3.2 (unreleased yet)
|
2
|
+
* <b>DEPRECATION NOTICE:</b>Ruby 1.8 support dropped ! Mongoid 3.0 only supports MRI 1.9.3, and HEAD, and JRuby 1.6.0+ in 1.9 mode
|
3
|
+
* removed <tt>dynamic_shortcuts</tt> arguments from the generator
|
4
|
+
* to use dynamic shortcuts feature when you're using ActiveRecord, you have to enable it _after_ running rake db:migrate as it relies on the roles table
|
5
|
+
* support for Mongoid 3.x (thanks to @Leonas)
|
6
|
+
* new class methods on the User class to find users depending on roles they have
|
7
|
+
* added scopes to Role class to be able to fetch global, class scoped and instance scoped roles for a specific user
|
8
|
+
* deletions of n-n relation are unreliable with Mongoid. Removing ids instead (thanks to @nfo)
|
9
|
+
* <tt>has_role?</tt> method now supports new instance (i.e. record not saved in the database yet) (thanks to @demental)
|
10
|
+
* added association callbacks <tt>(before|after)_add</tt>, <tt>(before|after)_remove</tt> on <tt>rolify</tt> method (thanks to @shekibobo)
|
11
|
+
* added ability to pass an array of roles to <tt>Resource.with_role()</tt>, aliased by <tt>Resource.with_roles()</tt> (thanks to @lukes)
|
12
|
+
* added option to have roles be destroyed by default if parent resource is destroyed (thanks to @treydock)
|
13
|
+
* better edge cases covering in the specs
|
14
|
+
* fixed a bug regarding the loading order of the railtie when using Mongoid ORM and other gems using initializer files (thanks to @stigi)
|
15
|
+
* fixed double quote syntax when using MySQL
|
16
|
+
* documentation improvement
|
17
|
+
|
1
18
|
= 3.1 (Apr 6, 2012)
|
2
19
|
* Mongoid adapter optimization
|
3
20
|
* adapter code refactoring
|
data/README.md
CHANGED
@@ -13,9 +13,10 @@ This library was intended to be used with [CanCan](https://github.com/ryanb/canc
|
|
13
13
|
|
14
14
|
## Requirements
|
15
15
|
|
16
|
-
* >=
|
17
|
-
* ActiveRecord
|
18
|
-
* supports ruby 1.
|
16
|
+
* Rails >= 3.1
|
17
|
+
* ActiveRecord >= 3.1 <b>or</b> Mongoid >= 3.0
|
18
|
+
* supports ruby 1.9, JRuby 1.6.0+ (in 1.9 mode) and Rubinius 2.0.0dev (in 1.9 mode)
|
19
|
+
* support of ruby 1.8 has been dropped due to Mongoid 3.0 that only supports 1.9 new hash syntax
|
19
20
|
|
20
21
|
## Installation
|
21
22
|
|
@@ -54,7 +55,41 @@ Let's migrate !
|
|
54
55
|
rake db:migrate
|
55
56
|
```
|
56
57
|
|
57
|
-
### 3.
|
58
|
+
### 3.1 Configure your user model
|
59
|
+
|
60
|
+
This gem adds the `rolify` method to your User class. You can also specify optional callbacks* on the user for when roles are added or removed:
|
61
|
+
|
62
|
+
```ruby
|
63
|
+
class User < ActiveRecord::Base
|
64
|
+
rolify :before_add => :before_add_method
|
65
|
+
|
66
|
+
def :before_add_method(role)
|
67
|
+
# do something before it gets added
|
68
|
+
end
|
69
|
+
end
|
70
|
+
```
|
71
|
+
|
72
|
+
The `rolify` method accepts the following callback* options:
|
73
|
+
|
74
|
+
- `before_add`
|
75
|
+
- `after_add`
|
76
|
+
- `before_remove`
|
77
|
+
- `after_remove`
|
78
|
+
|
79
|
+
*PLEASE NOTE: callbacks are currently only supported using ActiveRecord ORM. Mongoid will support association callbacks in its 3.1 release (Mongoid current version is 3.0.x)
|
80
|
+
|
81
|
+
### 3.2 Configure your resource models
|
82
|
+
|
83
|
+
In the resource models you want to apply roles on, just add ``resourcify`` method.
|
84
|
+
For example, on this ActiveRecord class:
|
85
|
+
|
86
|
+
```ruby
|
87
|
+
class Forum < ActiveRecord::Base
|
88
|
+
resourcify
|
89
|
+
end
|
90
|
+
```
|
91
|
+
|
92
|
+
### 4. Add a role to a user
|
58
93
|
|
59
94
|
To define a global role:
|
60
95
|
|
@@ -79,7 +114,7 @@ To define a role scoped to a resource class
|
|
79
114
|
|
80
115
|
That's it !
|
81
116
|
|
82
|
-
###
|
117
|
+
### 5. Role queries
|
83
118
|
|
84
119
|
To check if a user has a global role:
|
85
120
|
|
@@ -125,7 +160,7 @@ A global role overrides resource role request:
|
|
125
160
|
=> true
|
126
161
|
```
|
127
162
|
|
128
|
-
###
|
163
|
+
### 6. Resource roles querying
|
129
164
|
|
130
165
|
Starting from rolify 3.0, you can search roles on instance level or class level resources.
|
131
166
|
|
@@ -160,6 +195,7 @@ Starting from rolify 3.0, you can search roles on instance level or class level
|
|
160
195
|
* [Wiki](https://github.com/EppO/rolify/wiki)
|
161
196
|
* [Usage](https://github.com/EppO/rolify/wiki/Usage): all the available commands
|
162
197
|
* [Tutorial](https://github.com/EppO/rolify/wiki/Tutorial): how to use [rolify](http://eppo.github.com/rolify) with [Devise](https://github.com/plataformatec/devise) and [CanCan](https://github.com/ryanb/cancan).
|
198
|
+
* [Amazing tutorial](http://railsapps.github.com/tutorial-rails-bootstrap-devise-cancan.html) provided by [RailsApps](http://railsapps.github.com/)
|
163
199
|
|
164
200
|
## Questions or Problems?
|
165
201
|
|
@@ -9,14 +9,14 @@ module Rolify
|
|
9
9
|
argument :role_cname, :type => :string, :default => "Role"
|
10
10
|
argument :user_cname, :type => :string, :default => "User"
|
11
11
|
argument :orm_adapter, :type => :string, :default => "active_record"
|
12
|
-
class_option :dynamic_shortcuts, :type => :boolean, :default => false
|
12
|
+
#class_option :dynamic_shortcuts, :type => :boolean, :default => false
|
13
13
|
|
14
14
|
desc "Generates a model with the given NAME and a migration file."
|
15
15
|
|
16
16
|
def generate_role
|
17
17
|
template "role-#{orm_adapter}.rb", "app/models/#{role_cname.underscore}.rb"
|
18
|
-
|
19
|
-
"
|
18
|
+
inject_into_file(model_path, :after => inject_rolify_method) do
|
19
|
+
" rolify" + (role_cname == "Role" ? "" : " :role_cname => '#{role_cname.camelize}'") + "\n"
|
20
20
|
end
|
21
21
|
end
|
22
22
|
|
@@ -36,6 +36,14 @@ module Rolify
|
|
36
36
|
def show_readme
|
37
37
|
readme "README-#{orm_adapter}" if behavior == :invoke
|
38
38
|
end
|
39
|
+
|
40
|
+
def inject_rolify_method
|
41
|
+
if orm_adapter == "active_record"
|
42
|
+
/class #{user_cname.camelize}\n|class #{user_cname.camelize} .*\n/
|
43
|
+
else
|
44
|
+
/include Mongoid::Document\n|include Mongoid::Document .*\n/
|
45
|
+
end
|
46
|
+
end
|
39
47
|
end
|
40
48
|
end
|
41
49
|
end
|
@@ -3,5 +3,6 @@ Rolify.configure do |config|
|
|
3
3
|
<%= "# " if orm_adapter == "active_record" %>config.use_mongoid
|
4
4
|
|
5
5
|
# Dynamic shortcuts for User class (user.is_admin? like methods). Default is: false
|
6
|
-
|
6
|
+
# Enable this feature _after_ running rake db:migrate as it relies on the roles table
|
7
|
+
# config.use_dynamic_shortcuts
|
7
8
|
end
|
@@ -5,13 +5,15 @@ class <%= role_cname.camelize %>
|
|
5
5
|
belongs_to :resource, :polymorphic => true
|
6
6
|
|
7
7
|
field :name, :type => String
|
8
|
-
index :name, unique
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
)
|
8
|
+
index({ :name => 1 }, { :unique => true })
|
9
|
+
|
10
|
+
|
11
|
+
index({
|
12
|
+
:name => 1,
|
13
|
+
:resource_type => 1,
|
14
|
+
:resource_id => 1
|
15
|
+
},
|
16
|
+
{ :unique => true})
|
17
|
+
|
18
|
+
scopify
|
17
19
|
end
|
data/lib/rolify.rb
CHANGED
@@ -11,12 +11,16 @@ module Rolify
|
|
11
11
|
|
12
12
|
attr_accessor :role_cname, :adapter
|
13
13
|
|
14
|
-
def rolify(options = {
|
14
|
+
def rolify(options = {})
|
15
15
|
include Role
|
16
16
|
extend Dynamic if Rolify.dynamic_shortcuts
|
17
17
|
|
18
|
+
options.reverse_merge!({:role_cname => 'Role'})
|
19
|
+
|
18
20
|
rolify_options = { :class_name => options[:role_cname].camelize }
|
19
21
|
rolify_options.merge!({ :join_table => "#{self.to_s.tableize}_#{options[:role_cname].tableize}" }) if Rolify.orm == "active_record"
|
22
|
+
rolify_options.merge!(options.select{ |k,v| [:before_add, :after_add, :before_remove, :after_remove].include? k.to_sym }) if Rolify.orm == "active_record"
|
23
|
+
|
20
24
|
has_and_belongs_to_many :roles, rolify_options
|
21
25
|
|
22
26
|
self.adapter = Rolify::Adapter::Base.create("role_adapter", options[:role_cname], self.name)
|
@@ -25,18 +29,22 @@ module Rolify
|
|
25
29
|
load_dynamic_methods if Rolify.dynamic_shortcuts
|
26
30
|
end
|
27
31
|
|
28
|
-
def resourcify(options = { :role_cname => 'Role' })
|
32
|
+
def resourcify(options = { :role_cname => 'Role', :dependent => :destroy })
|
29
33
|
include Resource
|
30
34
|
|
31
|
-
resourcify_options = { :class_name => options[:role_cname].camelize }
|
32
|
-
resourcify_options.merge!({ :as => :resource })
|
35
|
+
resourcify_options = { :class_name => options[:role_cname].camelize, :as => :resource, :dependent => options[:dependent] }
|
33
36
|
has_many :roles, resourcify_options
|
34
37
|
|
35
38
|
self.adapter = Rolify::Adapter::Base.create("resource_adapter", options[:role_cname], self.name)
|
36
39
|
self.role_cname = options[:role_cname]
|
37
40
|
end
|
38
41
|
|
42
|
+
def scopify
|
43
|
+
require "rolify/adapters/#{Rolify.orm}/scopes.rb"
|
44
|
+
extend Rolify::Adapter::Scopes
|
45
|
+
end
|
46
|
+
|
39
47
|
def role_class
|
40
48
|
self.role_cname.constantize
|
41
49
|
end
|
42
|
-
end
|
50
|
+
end
|
@@ -4,13 +4,20 @@ module Rolify
|
|
4
4
|
module Adapter
|
5
5
|
class ResourceAdapter < ResourceAdapterBase
|
6
6
|
def resources_find(roles_table, relation, role_name)
|
7
|
-
resources = relation.joins("INNER JOIN
|
8
|
-
resources = resources.where("#{roles_table}.name
|
7
|
+
resources = relation.joins("INNER JOIN #{quote(roles_table)} ON #{quote(roles_table)}.resource_type = '#{relation.to_s}'")
|
8
|
+
resources = resources.where("#{quote(roles_table)}.name IN (?) AND #{quote(roles_table)}.resource_type = ?", Array(role_name), relation.to_s)
|
9
9
|
resources
|
10
10
|
end
|
11
11
|
|
12
|
-
def in(relation,
|
13
|
-
|
12
|
+
def in(relation, user, role_names)
|
13
|
+
roles = user.roles.where(:name => role_names)
|
14
|
+
relation.where("#{quote(role_class.to_s.tableize)}.id IN (?) AND ((resource_id = #{quote(relation.table_name)}.id) OR (resource_id IS NULL))", roles)
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def quote(column)
|
20
|
+
ActiveRecord::Base.connection.quote_column_name column
|
14
21
|
end
|
15
22
|
end
|
16
23
|
end
|
@@ -32,6 +32,13 @@ module Rolify
|
|
32
32
|
def exists?(relation, column)
|
33
33
|
relation.where("#{column} IS NOT NULL")
|
34
34
|
end
|
35
|
+
|
36
|
+
def scope(relation, conditions)
|
37
|
+
query = relation.scoped
|
38
|
+
query = query.joins(:roles)
|
39
|
+
query = where(query, conditions)
|
40
|
+
query
|
41
|
+
end
|
35
42
|
|
36
43
|
private
|
37
44
|
|
@@ -54,15 +61,15 @@ module Rolify
|
|
54
61
|
end
|
55
62
|
|
56
63
|
def build_query(role, resource = nil)
|
57
|
-
return [ "name = ?", [ role ] ] if resource == :any
|
58
|
-
query = "((name = ?) AND (resource_type IS NULL) AND (resource_id IS NULL))"
|
64
|
+
return [ "#{role_table}.name = ?", [ role ] ] if resource == :any
|
65
|
+
query = "((#{role_table}.name = ?) AND (#{role_table}.resource_type IS NULL) AND (#{role_table}.resource_id IS NULL))"
|
59
66
|
values = [ role ]
|
60
67
|
if resource
|
61
68
|
query.insert(0, "(")
|
62
|
-
query += " OR ((name = ?) AND (resource_type = ?) AND (resource_id IS NULL))"
|
69
|
+
query += " OR ((#{role_table}.name = ?) AND (#{role_table}.resource_type = ?) AND (#{role_table}.resource_id IS NULL))"
|
63
70
|
values << role << (resource.is_a?(Class) ? resource.to_s : resource.class.name)
|
64
71
|
if !resource.is_a? Class
|
65
|
-
query += " OR ((name = ?) AND (resource_type = ?) AND (resource_id = ?))"
|
72
|
+
query += " OR ((#{role_table}.name = ?) AND (#{role_table}.resource_type = ?) AND (#{role_table}.resource_id = ?))"
|
66
73
|
values << role << resource.class.name << resource.id
|
67
74
|
end
|
68
75
|
query += ")"
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Rolify
|
2
|
+
module Adapter
|
3
|
+
module Scopes
|
4
|
+
def global
|
5
|
+
where(:resource_type => nil, :resource_id => nil)
|
6
|
+
end
|
7
|
+
|
8
|
+
def class_scoped(resource_type = nil)
|
9
|
+
where_conditions = "resource_type IS NOT NULL AND resource_id IS NULL"
|
10
|
+
where_conditions = [ "resource_type = ? AND resource_id IS NULL", resource_type.name ] if resource_type
|
11
|
+
where(where_conditions)
|
12
|
+
end
|
13
|
+
|
14
|
+
def instance_scoped(resource_type = nil)
|
15
|
+
where_conditions = "resource_type IS NOT NULL AND resource_id IS NOT NULL"
|
16
|
+
if resource_type
|
17
|
+
if resource_type.is_a? Class
|
18
|
+
where_conditions = [ "resource_type = ? AND resource_id IS NOT NULL", resource_type.name ]
|
19
|
+
else
|
20
|
+
where_conditions = [ "resource_type = ? AND resource_id = ?", resource_type.class.name, resource_type.id ]
|
21
|
+
end
|
22
|
+
end
|
23
|
+
where(where_conditions)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
data/lib/rolify/adapters/base.rb
CHANGED
@@ -14,8 +14,13 @@ module Rolify
|
|
14
14
|
@user_cname.constantize
|
15
15
|
end
|
16
16
|
|
17
|
+
def role_table
|
18
|
+
@role_cname.tableize
|
19
|
+
end
|
20
|
+
|
17
21
|
def self.create(adapter, role_cname, user_cname)
|
18
22
|
load "rolify/adapters/#{Rolify.orm}/#{adapter}.rb"
|
23
|
+
load "rolify/adapters/#{Rolify.orm}/scopes.rb"
|
19
24
|
Rolify::Adapter.const_get(adapter.camelize.to_sym).new(role_cname, user_cname)
|
20
25
|
end
|
21
26
|
end
|
@@ -4,16 +4,20 @@ module Rolify
|
|
4
4
|
module Adapter
|
5
5
|
class ResourceAdapter < ResourceAdapterBase
|
6
6
|
def resources_find(roles_table, relation, role_name)
|
7
|
-
roles = roles_table.classify.constantize.where(:name => role_name, :resource_type => relation.to_s)
|
7
|
+
roles = roles_table.classify.constantize.where(:name.in => Array(role_name), :resource_type => relation.to_s)
|
8
8
|
resources = []
|
9
9
|
roles.each do |role|
|
10
|
-
|
11
|
-
|
10
|
+
if role.resource_id.nil?
|
11
|
+
resources += relation.all
|
12
|
+
else
|
13
|
+
resources << role.resource
|
14
|
+
end
|
12
15
|
end
|
13
|
-
resources
|
16
|
+
resources.uniq
|
14
17
|
end
|
15
18
|
|
16
|
-
def in(resources,
|
19
|
+
def in(resources, user, role_names)
|
20
|
+
roles = user.roles.where(:name.in => Array(role_names))
|
17
21
|
return [] if resources.empty? || roles.empty?
|
18
22
|
resources.delete_if { |resource| (resource.applied_roles & roles).empty? }
|
19
23
|
resources
|
@@ -24,8 +24,13 @@ module Rolify
|
|
24
24
|
roles.merge!({ :resource_id => resource.id }) if resource && !resource.is_a?(Class)
|
25
25
|
roles_to_remove = relation.roles.where(roles)
|
26
26
|
roles_to_remove.each do |role|
|
27
|
-
|
28
|
-
role
|
27
|
+
# Deletion in n-n relations is unreliable. Sometimes it works, sometimes not.
|
28
|
+
# So, this does not work all the time: `relation.roles.delete(role)`
|
29
|
+
# @see http://stackoverflow.com/questions/9132596/rails3-mongoid-many-to-many-relation-and-delete-operation
|
30
|
+
# We instead remove ids from the Role object and the relation object.
|
31
|
+
relation.role_ids.delete(role.id)
|
32
|
+
role.send((user_class.to_s.underscore + '_ids').to_sym).delete(relation.id)
|
33
|
+
|
29
34
|
role.destroy if role.send(user_class.to_s.tableize.to_sym).empty?
|
30
35
|
end
|
31
36
|
end
|
@@ -33,6 +38,13 @@ module Rolify
|
|
33
38
|
def exists?(relation, column)
|
34
39
|
relation.where(column.to_sym.ne => nil)
|
35
40
|
end
|
41
|
+
|
42
|
+
def scope(relation, conditions)
|
43
|
+
roles = where(role_class, conditions).map { |role| role.id }
|
44
|
+
return [] if roles.size.zero?
|
45
|
+
query = relation.any_in(:role_ids => roles)
|
46
|
+
query
|
47
|
+
end
|
36
48
|
|
37
49
|
private
|
38
50
|
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Rolify
|
2
|
+
module Adapter
|
3
|
+
module Scopes
|
4
|
+
def global
|
5
|
+
where(:resource_type => nil, :resource_id => nil)
|
6
|
+
end
|
7
|
+
|
8
|
+
def class_scoped(resource_type = nil)
|
9
|
+
where_conditions = { :resource_type.ne => nil, :resource_id => nil }
|
10
|
+
where_conditions = { :resource_type => resource_type.name, :resource_id => nil } if resource_type
|
11
|
+
where(where_conditions)
|
12
|
+
end
|
13
|
+
|
14
|
+
def instance_scoped(resource_type = nil)
|
15
|
+
where_conditions = { :resource_type.ne => nil, :resource_id.ne => nil }
|
16
|
+
if resource_type
|
17
|
+
if resource_type.is_a? Class
|
18
|
+
where_conditions = { :resource_type => resource_type.name, :resource_id.ne => nil }
|
19
|
+
else
|
20
|
+
where_conditions = { :resource_type => resource_type.class.name, :resource_id => resource_type.id }
|
21
|
+
end
|
22
|
+
end
|
23
|
+
where(where_conditions)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module Rolify
|
2
|
+
module Finders
|
3
|
+
def with_role(role_name, resource = nil)
|
4
|
+
self.adapter.scope(self, :name => role_name, :resource => resource)
|
5
|
+
end
|
6
|
+
|
7
|
+
def with_all_roles(*args)
|
8
|
+
users = []
|
9
|
+
args.each do |arg|
|
10
|
+
if arg.is_a? Hash
|
11
|
+
users_to_add = self.with_role(arg[:name], arg[:resource])
|
12
|
+
elsif arg.is_a?(String) || arg.is_a?(Symbol)
|
13
|
+
users_to_add = self.with_role(arg)
|
14
|
+
else
|
15
|
+
raise ArgumentError, "Invalid argument type: only hash or string or symbol allowed"
|
16
|
+
end
|
17
|
+
users = users_to_add if users.empty?
|
18
|
+
users &= users_to_add
|
19
|
+
return [] if users.empty?
|
20
|
+
end
|
21
|
+
users
|
22
|
+
end
|
23
|
+
|
24
|
+
def with_any_role(*args)
|
25
|
+
users = []
|
26
|
+
args.each do |arg|
|
27
|
+
if arg.is_a? Hash
|
28
|
+
users_to_add = self.with_role(arg[:name], arg[:resource])
|
29
|
+
elsif arg.is_a?(String) || arg.is_a?(Symbol)
|
30
|
+
users_to_add = self.with_role(arg)
|
31
|
+
else
|
32
|
+
raise ArgumentError, "Invalid argument type: only hash or string or symbol allowed"
|
33
|
+
end
|
34
|
+
users += users_to_add
|
35
|
+
end
|
36
|
+
users.uniq
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|