rolify 3.1.0 → 4.0.0

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.
Files changed (78) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +4 -1
  3. data/.travis.yml +44 -11
  4. data/CHANGELOG.rdoc +70 -0
  5. data/CONTRIBUTORS +6 -0
  6. data/Gemfile +21 -2
  7. data/README.md +130 -68
  8. data/Rakefile +29 -4
  9. data/UPGRADE.rdoc +22 -0
  10. data/circle.yml +13 -0
  11. data/gemfiles/Gemfile.rails-3.2 +27 -0
  12. data/gemfiles/Gemfile.rails-4.0 +33 -0
  13. data/gemfiles/Gemfile.rails-4.1 +37 -0
  14. data/lib/generators/active_record/rolify_generator.rb +54 -0
  15. data/lib/generators/active_record/templates/README +8 -0
  16. data/lib/generators/active_record/templates/migration.rb +19 -0
  17. data/lib/generators/mongoid/rolify_generator.rb +55 -0
  18. data/lib/generators/mongoid/templates/README-mongoid +4 -0
  19. data/lib/generators/rolify/rolify_generator.rb +35 -0
  20. data/lib/generators/rolify/{role/templates/README-mongoid → templates/README} +1 -5
  21. data/lib/generators/rolify/templates/initializer.rb +7 -0
  22. data/lib/generators/rolify/templates/role-active_record.rb +11 -0
  23. data/lib/generators/rolify/{role/templates → templates}/role-mongoid.rb +9 -9
  24. data/lib/generators/rolify/user_generator.rb +39 -0
  25. data/lib/rolify/adapters/active_record/resource_adapter.rb +36 -6
  26. data/lib/rolify/adapters/active_record/role_adapter.rb +25 -13
  27. data/lib/rolify/adapters/active_record/scopes.rb +27 -0
  28. data/lib/rolify/adapters/base.rb +9 -0
  29. data/lib/rolify/adapters/mongoid/resource_adapter.rb +27 -6
  30. data/lib/rolify/adapters/mongoid/role_adapter.rb +35 -11
  31. data/lib/rolify/adapters/mongoid/scopes.rb +27 -0
  32. data/lib/rolify/configure.rb +36 -5
  33. data/lib/rolify/finders.rb +40 -0
  34. data/lib/rolify/matchers.rb +31 -0
  35. data/lib/rolify/railtie.rb +1 -1
  36. data/lib/rolify/resource.rb +19 -10
  37. data/lib/rolify/role.rb +33 -13
  38. data/lib/rolify/version.rb +1 -1
  39. data/lib/rolify.rb +46 -20
  40. data/rolify.gemspec +18 -24
  41. data/spec/README.rdoc +24 -0
  42. data/spec/generators/rolify/rolify_activerecord_generator_spec.rb +165 -0
  43. data/spec/generators/rolify/rolify_mongoid_generator_spec.rb +113 -0
  44. data/spec/generators_helper.rb +27 -0
  45. data/spec/rolify/config_spec.rb +20 -21
  46. data/spec/rolify/custom_spec.rb +11 -6
  47. data/spec/rolify/matchers_spec.rb +24 -0
  48. data/spec/rolify/namespace_spec.rb +24 -0
  49. data/spec/rolify/resource_spec.rb +135 -37
  50. data/spec/rolify/resourcifed_and_rolifed_spec.rb +24 -0
  51. data/spec/rolify/role_spec.rb +8 -9
  52. data/spec/rolify/shared_contexts.rb +22 -3
  53. data/spec/rolify/shared_examples/shared_examples_for_add_role.rb +10 -17
  54. data/spec/rolify/shared_examples/shared_examples_for_callbacks.rb +65 -0
  55. data/spec/rolify/shared_examples/shared_examples_for_dynamic.rb +64 -27
  56. data/spec/rolify/shared_examples/shared_examples_for_finders.rb +81 -0
  57. data/spec/rolify/shared_examples/shared_examples_for_has_all_roles.rb +29 -29
  58. data/spec/rolify/shared_examples/shared_examples_for_has_any_role.rb +35 -35
  59. data/spec/rolify/shared_examples/shared_examples_for_has_role.rb +38 -38
  60. data/spec/rolify/shared_examples/shared_examples_for_only_has_role.rb +174 -0
  61. data/spec/rolify/shared_examples/shared_examples_for_remove_role.rb +28 -59
  62. data/spec/rolify/shared_examples/shared_examples_for_roles.rb +58 -32
  63. data/spec/rolify/shared_examples/shared_examples_for_scopes.rb +38 -0
  64. data/spec/spec_helper.rb +39 -3
  65. data/spec/support/adapters/active_record.rb +58 -7
  66. data/spec/support/adapters/mongoid.rb +110 -17
  67. data/spec/support/adapters/mongoid.yml +6 -0
  68. data/spec/support/data.rb +18 -15
  69. data/spec/support/schema.rb +31 -16
  70. data/spec/support/stream_helpers.rb +18 -0
  71. metadata +88 -84
  72. data/lib/generators/rolify/role/role_generator.rb +0 -41
  73. data/lib/generators/rolify/role/templates/README +0 -11
  74. data/lib/generators/rolify/role/templates/README-active_record +0 -21
  75. data/lib/generators/rolify/role/templates/initializer.rb +0 -7
  76. data/lib/generators/rolify/role/templates/migration.rb +0 -19
  77. data/lib/generators/rolify/role/templates/role-active_record.rb +0 -4
  78. data/spec/generators/rolify/role/role_generator_spec.rb +0 -197
@@ -0,0 +1,54 @@
1
+ require 'rails/generators/active_record'
2
+ require 'active_support/core_ext'
3
+
4
+ module ActiveRecord
5
+ module Generators
6
+ class RolifyGenerator < ActiveRecord::Generators::Base
7
+ source_root File.expand_path("../templates", __FILE__)
8
+
9
+ argument :user_cname, :type => :string, :default => "User", :banner => "User"
10
+
11
+ def generate_model
12
+ invoke "active_record:model", [ name ], :migration => false
13
+ end
14
+
15
+ def inject_role_class
16
+ inject_into_class(model_path, class_name, model_content)
17
+ end
18
+
19
+ def copy_rolify_migration
20
+ migration_template "migration.rb", "db/migrate/rolify_create_#{table_name}.rb"
21
+ end
22
+
23
+ def join_table
24
+ user_cname.constantize.table_name + "_" + table_name
25
+ end
26
+
27
+ def user_reference
28
+ user_cname.demodulize.underscore
29
+ end
30
+
31
+ def role_reference
32
+ class_name.demodulize.underscore
33
+ end
34
+
35
+ def model_path
36
+ File.join("app", "models", "#{file_path}.rb")
37
+ end
38
+
39
+ def model_content
40
+ content = <<RUBY
41
+ has_and_belongs_to_many :%{user_cname}, :join_table => :%{join_table}
42
+ belongs_to :resource, :polymorphic => true
43
+
44
+ validates :resource_type,
45
+ :inclusion => { :in => Rolify.resource_types },
46
+ :allow_nil => true
47
+
48
+ scopify
49
+ RUBY
50
+ content % { :user_cname => user_cname.constantize.table_name, :join_table => "#{user_cname.constantize.table_name}_#{table_name}"}
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,8 @@
1
+ Now, you just have to run the migration using rake command:
2
+
3
+ rake db:migrate
4
+
5
+ and you will be able to add the resourcify method inside all models you want
6
+ scoped by a role.
7
+
8
+ ===============================================================================
@@ -0,0 +1,19 @@
1
+ class RolifyCreate<%= table_name.camelize %> < ActiveRecord::Migration
2
+ def change
3
+ create_table(:<%= table_name %>) do |t|
4
+ t.string :name
5
+ t.references :resource, :polymorphic => true
6
+
7
+ t.timestamps
8
+ end
9
+
10
+ create_table(:<%= join_table %>, :id => false) do |t|
11
+ t.references :<%= user_reference %>
12
+ t.references :<%= role_reference %>
13
+ end
14
+
15
+ add_index(:<%= table_name %>, :name)
16
+ add_index(:<%= table_name %>, [ :name, :resource_type, :resource_id ])
17
+ add_index(:<%= join_table %>, [ :<%= user_reference %>_id, :<%= role_reference %>_id ])
18
+ end
19
+ end
@@ -0,0 +1,55 @@
1
+ require 'rails/generators/mongoid_generator'
2
+ require 'active_support/core_ext'
3
+
4
+ module Mongoid
5
+ module Generators
6
+ class RolifyGenerator < Rails::Generators::NamedBase
7
+ source_root File.expand_path("../templates", __FILE__)
8
+
9
+ argument :user_cname, :type => :string, :default => "User", :banner => "User"
10
+
11
+ def generate_model
12
+ invoke "mongoid:model", [ name ]
13
+ end
14
+
15
+ def inject_role_class
16
+ inject_into_file(model_path, model_contents, :after => "include Mongoid::Document\n")
17
+ end
18
+
19
+ def user_reference
20
+ user_cname.demodulize.underscore
21
+ end
22
+
23
+ def role_reference
24
+ class_name.demodulize.underscore
25
+ end
26
+
27
+ def model_path
28
+ File.join("app", "models", "#{file_path}.rb")
29
+ end
30
+
31
+ def model_contents
32
+ content = <<RUBY
33
+ has_and_belongs_to_many :%{user_cname}
34
+ belongs_to :resource, :polymorphic => true
35
+
36
+ field :name, :type => String
37
+
38
+ index({
39
+ :name => 1,
40
+ :resource_type => 1,
41
+ :resource_id => 1
42
+ },
43
+ { :unique => true})
44
+
45
+ validates :resource_type,
46
+ :inclusion => { :in => Rolify.resource_types },
47
+ :allow_nil => true
48
+
49
+ scopify
50
+ RUBY
51
+ content % { :user_cname => user_cname.constantize.collection_name }
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,4 @@
1
+ Now, you are able to add the resourcify method inside all models you want
2
+ scoped by a role.
3
+
4
+ ===============================================================================
@@ -0,0 +1,35 @@
1
+ module Rolify
2
+ module Generators
3
+ class RolifyGenerator < Rails::Generators::NamedBase
4
+ Rails::Generators::ResourceHelpers
5
+
6
+ source_root File.expand_path('../templates', __FILE__)
7
+ argument :user_cname, :type => :string, :default => "User"
8
+
9
+ namespace :rolify
10
+ hook_for :orm, :required => true
11
+
12
+ desc "Generates a model with the given NAME and a migration file."
13
+
14
+ def self.start(args, config)
15
+ user_cname = args.size > 1 ? args[1] : "User"
16
+ args.insert(1, user_cname) # 0 being the view name
17
+ super
18
+ end
19
+
20
+ def inject_user_class
21
+ invoke "rolify:user", [ user_cname, class_name ], :orm => options.orm
22
+ end
23
+
24
+ def copy_initializer_file
25
+ template "initializer.rb", "config/initializers/rolify.rb"
26
+ end
27
+
28
+ def show_readme
29
+ if behavior == :invoke
30
+ readme "README"
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -4,14 +4,10 @@ An initializer file has been created here: config/initializers/rolify.rb, you
4
4
  can change rolify settings to match your needs.
5
5
  Defaults values are commented out.
6
6
 
7
- A Role class has been been created in app/models (with the name you gave as
7
+ A Role class has been created in app/models (with the name you gave as
8
8
  argument otherwise the default is role.rb), you can add your own business logic
9
9
  inside.
10
10
 
11
11
  Inside your User class (or the name you gave as argument otherwise the default
12
12
  is user.rb), rolify method has been inserted to provide rolify methods.
13
13
 
14
- Now, if you are able to add the resourcify method inside all models you want
15
- scoped by a role.
16
-
17
- ===============================================================================
@@ -0,0 +1,7 @@
1
+ Rolify.configure<%= "(\"#{class_name.camelize.to_s}\")" if class_name != "Role" %> do |config|
2
+ # By default ORM adapter is ActiveRecord. uncomment to use mongoid
3
+ <%= "# " if options.orm == :active_record || !options.orm %>config.use_mongoid
4
+
5
+ # Dynamic shortcuts for User class (user.is_admin? like methods). Default is: false
6
+ # config.use_dynamic_shortcuts
7
+ end
@@ -0,0 +1,11 @@
1
+ class <%= role_cname.camelize %> < ActiveRecord::Base
2
+ <% if need_table_prefix?(role_cname) %>
3
+ def self.table_name_prefix
4
+ <%= table_prefix(role_cname) %>_
5
+ end
6
+ <% end %>
7
+ has_and_belongs_to_many :<%= user_cname.tableize %>, :join_table => :<%= "#{table_name(user_cname, true)}_#{table_name(role_cname, true)}" %>
8
+ belongs_to :resource, :polymorphic => true
9
+
10
+ scopify
11
+ end
@@ -5,13 +5,13 @@ class <%= role_cname.camelize %>
5
5
  belongs_to :resource, :polymorphic => true
6
6
 
7
7
  field :name, :type => String
8
- index :name, unique: true
9
- index(
10
- [
11
- [:name, Mongo::ASCENDING],
12
- [:resource_type, Mongo::ASCENDING],
13
- [:resource_id, Mongo::ASCENDING]
14
- ],
15
- unique: true
16
- )
8
+
9
+ index({
10
+ :name => 1,
11
+ :resource_type => 1,
12
+ :resource_id => 1
13
+ },
14
+ { :unique => true})
15
+
16
+ scopify
17
17
  end
@@ -0,0 +1,39 @@
1
+ require 'rails/generators/migration'
2
+ require 'active_support/core_ext'
3
+
4
+ module Rolify
5
+ module Generators
6
+ class UserGenerator < Rails::Generators::NamedBase
7
+ argument :role_cname, :type => :string, :default => "Role"
8
+ class_option :orm, :type => :string, :default => "active_record"
9
+
10
+ desc "Inject rolify method in the User class."
11
+
12
+ def inject_user_content
13
+ inject_into_file(model_path, :after => inject_rolify_method) do
14
+ " rolify#{role_association}\n"
15
+ end
16
+ end
17
+
18
+ def inject_rolify_method
19
+ if options.orm == :active_record
20
+ /class #{class_name.camelize}\n|class #{class_name.camelize} .*\n|class #{class_name.demodulize.camelize}\n|class #{class_name.demodulize.camelize} .*\n/
21
+ else
22
+ /include Mongoid::Document\n|include Mongoid::Document .*\n/
23
+ end
24
+ end
25
+
26
+ def model_path
27
+ File.join("app", "models", "#{file_path}.rb")
28
+ end
29
+
30
+ def role_association
31
+ if role_cname != "Role"
32
+ " :role_cname => '#{role_cname.camelize}'"
33
+ else
34
+ ""
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -1,17 +1,47 @@
1
1
  require 'rolify/adapters/base'
2
2
 
3
3
  module Rolify
4
- module Adapter
4
+ module Adapter
5
5
  class ResourceAdapter < ResourceAdapterBase
6
+ def find_roles(role_name, relation, user)
7
+ roles = user && (user != :any) ? user.roles : self.role_class
8
+ roles = roles.where('resource_type IN (?)', self.relation_types_for(relation))
9
+ roles = roles.where(:name => role_name.to_s) if role_name && (role_name != :any)
10
+ roles
11
+ end
12
+
6
13
  def resources_find(roles_table, relation, role_name)
7
- resources = relation.joins("INNER JOIN \"#{roles_table}\" ON \"#{roles_table}\".\"resource_type\" = '#{relation.to_s}'")
8
- resources = resources.where("#{roles_table}.name = ? AND #{roles_table}.resource_type = ?", role_name, relation.to_s)
14
+ klasses = self.relation_types_for(relation)
15
+ relations = klasses.inject('') do |str, klass|
16
+ str = "#{str}'#{klass.to_s}'"
17
+ str << ', ' unless klass == klasses.last
18
+ str
19
+ end
20
+ resources = relation.joins("INNER JOIN #{quote(roles_table)} ON #{quote(roles_table)}.resource_type IN (#{relations}) AND
21
+ (#{quote(roles_table)}.resource_id IS NULL OR #{quote(roles_table)}.resource_id = #{quote(relation.table_name)}.#{relation.primary_key})")
22
+ resources = resources.where("#{quote(roles_table)}.name IN (?) AND #{quote(roles_table)}.resource_type IN (?)", Array(role_name), klasses)
23
+ resources = resources.select("#{quote(relation.table_name)}.*")
9
24
  resources
10
25
  end
11
26
 
12
- def in(relation, roles)
13
- relation.where("#{role_class.to_s.tableize}.id IN (?) AND ((resource_id = #{relation.table_name}.id) OR (resource_id IS NULL))", roles)
27
+ def in(relation, user, role_names)
28
+ roles = user.roles.where(:name => role_names).select("#{quote(role_class.table_name)}.#{role_class.primary_key}")
29
+ relation.where("#{quote(role_class.table_name)}.#{role_class.primary_key} IN (?) AND ((resource_id = #{quote(relation.table_name)}.#{relation.primary_key}) OR (resource_id IS NULL))", roles)
30
+ end
31
+
32
+ def applied_roles(relation, children)
33
+ if children
34
+ relation.role_class.where('resource_type IN (?) AND resource_id IS NULL', self.relation_types_for(relation))
35
+ else
36
+ relation.role_class.where('resource_type = ? AND resource_id IS NULL', relation.to_s)
37
+ end
38
+ end
39
+
40
+ private
41
+
42
+ def quote(column)
43
+ ActiveRecord::Base.connection.quote_column_name column
14
44
  end
15
45
  end
16
46
  end
17
- end
47
+ end
@@ -1,7 +1,7 @@
1
1
  require 'rolify/adapters/base'
2
2
 
3
3
  module Rolify
4
- module Adapter
4
+ module Adapter
5
5
  class RoleAdapter < RoleAdapterBase
6
6
  def where(relation, *args)
7
7
  conditions, values = build_conditions(relation, args)
@@ -9,7 +9,7 @@ module Rolify
9
9
  end
10
10
 
11
11
  def find_or_create_by(role_name, resource_type = nil, resource_id = nil)
12
- role_class.find_or_create_by_name_and_resource_type_and_resource_id(role_name, resource_type, resource_id)
12
+ role_class.where(:name => role_name, :resource_type => resource_type, :resource_id => resource_id).first_or_create
13
13
  end
14
14
 
15
15
  def add(relation, role)
@@ -17,14 +17,15 @@ module Rolify
17
17
  end
18
18
 
19
19
  def remove(relation, role_name, resource = nil)
20
- roles = relation.roles.where(:name => role_name)
21
- roles = roles.where(:resource_type => (resource.is_a?(Class) ? resource.to_s : resource.class.name)) if resource
22
- roles = roles.where(:resource_id => resource.id) if resource && !resource.is_a?(Class)
20
+ cond = { :name => role_name }
21
+ cond[:resource_type] = (resource.is_a?(Class) ? resource.to_s : resource.class.name) if resource
22
+ cond[:resource_id] = resource.id if resource && !resource.is_a?(Class)
23
+ roles = relation.roles.where(cond)
23
24
  if roles
24
25
  relation.roles.delete(roles)
25
- roles.each do |role|
26
- role.destroy if role.send(user_class.table_name.to_sym).empty?
27
- end
26
+ roles.each do |role|
27
+ role.destroy if role.send(ActiveSupport::Inflector.demodulize(user_class).tableize.to_sym).limit(1).empty?
28
+ end if Rolify.remove_role_if_empty
28
29
  end
29
30
  roles
30
31
  end
@@ -33,6 +34,17 @@ module Rolify
33
34
  relation.where("#{column} IS NOT NULL")
34
35
  end
35
36
 
37
+ def scope(relation, conditions)
38
+ if Rails.version < "4.0"
39
+ query = relation.scoped
40
+ else
41
+ query = relation.all
42
+ end
43
+ query = query.joins(:roles)
44
+ query = where(query, conditions)
45
+ query
46
+ end
47
+
36
48
  private
37
49
 
38
50
  def build_conditions(relation, args)
@@ -54,15 +66,15 @@ module Rolify
54
66
  end
55
67
 
56
68
  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))"
69
+ return [ "#{role_table}.name = ?", [ role ] ] if resource == :any
70
+ query = "((#{role_table}.name = ?) AND (#{role_table}.resource_type IS NULL) AND (#{role_table}.resource_id IS NULL))"
59
71
  values = [ role ]
60
72
  if resource
61
73
  query.insert(0, "(")
62
- query += " OR ((name = ?) AND (resource_type = ?) AND (resource_id IS NULL))"
74
+ query += " OR ((#{role_table}.name = ?) AND (#{role_table}.resource_type = ?) AND (#{role_table}.resource_id IS NULL))"
63
75
  values << role << (resource.is_a?(Class) ? resource.to_s : resource.class.name)
64
76
  if !resource.is_a? Class
65
- query += " OR ((name = ?) AND (resource_type = ?) AND (resource_id = ?))"
77
+ query += " OR ((#{role_table}.name = ?) AND (#{role_table}.resource_type = ?) AND (#{role_table}.resource_id = ?))"
66
78
  values << role << resource.class.name << resource.id
67
79
  end
68
80
  query += ")"
@@ -71,4 +83,4 @@ module Rolify
71
83
  end
72
84
  end
73
85
  end
74
- end
86
+ end
@@ -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
@@ -14,10 +14,19 @@ module Rolify
14
14
  @user_cname.constantize
15
15
  end
16
16
 
17
+ def role_table
18
+ role_class.table_name
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
26
+
27
+ def relation_types_for(relation)
28
+ relation.descendants.map(&:to_s).push(relation.to_s)
29
+ end
21
30
  end
22
31
 
23
32
  class RoleAdapterBase < Adapter::Base
@@ -1,23 +1,44 @@
1
1
  require 'rolify/adapters/base'
2
2
 
3
3
  module Rolify
4
- module Adapter
4
+ module Adapter
5
5
  class ResourceAdapter < ResourceAdapterBase
6
+
7
+ def find_roles(role_name, relation, user)
8
+ roles = user && (user != :any) ? user.roles : self.role_class
9
+ roles = roles.where(:resource_type.in => self.relation_types_for(relation))
10
+ roles = roles.where(:name => role_name.to_s) if role_name && (role_name != :any)
11
+ roles
12
+ end
13
+
6
14
  def resources_find(roles_table, relation, role_name)
7
- roles = roles_table.classify.constantize.where(:name => role_name, :resource_type => relation.to_s)
15
+ roles = roles_table.classify.constantize.where(:name.in => Array(role_name), :resource_type.in => self.relation_types_for(relation))
8
16
  resources = []
9
17
  roles.each do |role|
10
- return relation.all if role.resource_id.nil?
11
- resources << role.resource
18
+ if role.resource_id.nil?
19
+ resources += relation.all
20
+ else
21
+ resources << role.resource
22
+ end
12
23
  end
13
- resources
24
+ resources.compact.uniq
14
25
  end
15
26
 
16
- def in(resources, roles)
27
+ def in(resources, user, role_names)
28
+ roles = user.roles.where(:name.in => Array(role_names))
17
29
  return [] if resources.empty? || roles.empty?
18
30
  resources.delete_if { |resource| (resource.applied_roles & roles).empty? }
19
31
  resources
20
32
  end
33
+
34
+ def applied_roles(relation, children)
35
+ if children
36
+ relation.role_class.where(:resource_type.in => self.relation_types_for(relation), :resource_id => nil)
37
+ else
38
+ relation.role_class.where(:resource_type => relation.to_s, :resource_id => nil)
39
+ end
40
+ end
41
+
21
42
  end
22
43
  end
23
44
  end
@@ -9,8 +9,8 @@ module Rolify
9
9
  end
10
10
 
11
11
  def find_or_create_by(role_name, resource_type = nil, resource_id = nil)
12
- self.role_class.find_or_create_by(:name => role_name,
13
- :resource_type => resource_type,
12
+ self.role_class.find_or_create_by(:name => role_name,
13
+ :resource_type => resource_type,
14
14
  :resource_id => resource_id)
15
15
  end
16
16
 
@@ -19,21 +19,45 @@ module Rolify
19
19
  end
20
20
 
21
21
  def remove(relation, role_name, resource = nil)
22
- roles = { :name => role_name }
23
- roles.merge!({:resource_type => (resource.is_a?(Class) ? resource.to_s : resource.class.name)}) if resource
24
- roles.merge!({ :resource_id => resource.id }) if resource && !resource.is_a?(Class)
25
- roles_to_remove = relation.roles.where(roles)
26
- roles_to_remove.each do |role|
22
+ #roles = { :name => role_name }
23
+ #roles.merge!({:resource_type => (resource.is_a?(Class) ? resource.to_s : resource.class.name)}) if resource
24
+ #roles.merge!({ :resource_id => resource.id }) if resource && !resource.is_a?(Class)
25
+ #roles_to_remove = relation.roles.where(roles)
26
+ #roles_to_remove.each do |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
+ #
34
+ # role.destroy if role.send(user_class.to_s.tableize.to_sym).empty?
35
+ #end
36
+ cond = { :name => role_name }
37
+ cond[:resource_type] = (resource.is_a?(Class) ? resource.to_s : resource.class.name) if resource
38
+ cond[:resource_id] = resource.id if resource && !resource.is_a?(Class)
39
+ roles = relation.roles.where(cond)
40
+ roles.each do |role|
27
41
  relation.roles.delete(role)
28
- role.reload
29
- role.destroy if role.send(user_class.to_s.tableize.to_sym).empty?
30
- end
42
+ role.send(ActiveSupport::Inflector.demodulize(user_class).tableize.to_sym).delete(relation)
43
+ if Rolify.remove_role_if_empty && role.send(ActiveSupport::Inflector.demodulize(user_class).tableize.to_sym).empty?
44
+ role.destroy
45
+ end
46
+ end if roles
47
+ roles
31
48
  end
32
49
 
33
50
  def exists?(relation, column)
34
51
  relation.where(column.to_sym.ne => nil)
35
52
  end
36
53
 
54
+ def scope(relation, conditions)
55
+ roles = where(role_class, conditions).map { |role| role.id }
56
+ return [] if roles.size.zero?
57
+ query = relation.any_in(:role_ids => roles)
58
+ query
59
+ end
60
+
37
61
  private
38
62
 
39
63
  def build_conditions(relation, args)
@@ -64,4 +88,4 @@ module Rolify
64
88
  end
65
89
  end
66
90
  end
67
- end
91
+ end
@@ -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