Browse files

preloading roles feature

  • Loading branch information...
1 parent eecba3b commit dfb2e5a76f91899858e5cdeb4a3f2fea753fda37 @matthewvermaak committed May 13, 2010
View
15 README.rdoc
@@ -55,8 +55,6 @@ Be sure to rake db:migrate to produce the roles table.
To run the Sanction test suite, which was generated with the help of plugin_a_week's plugin_test_helper, step into the
vendor/plugins/sanction and run rake test.
-You can also view the result of the last test build online @ http://runcoderun.com/matthewvermaak
-
=Config
===Example
@@ -210,6 +208,19 @@ Each of the following methods are injected at the instance and class level. (Exc
[Only as a Class Method]
For the COUNT QUIRK.
+<b>Eager Loading / Preloading</b>
+
+Consider the use case of querying for a result set, and driling into that set with role based questions at the instance level.
+To avoid 1+N query related performance issues, you can:
+
+ @people = Person.find(:all, :preload_roles => true)
+
+Subsequent calls to the Sanction API on those instances will no longer query the DB, but instead use the preloaded cache.
+
+ @people.each do |person|
+ person.has?(:some_role) # Does NOT hit the DB
+ end
+
<b>Rake tasks</b>
* <tt>rake sanction:role:describe</tt>
View
16 app/models/sanction/role.rb
@@ -111,6 +111,22 @@ def permissionable_klass
end
end
+ def principal_match?(instance_or_klass)
+ if instance_or_klass.is_a? Class
+ self.principal_type == instance_or_klass.name
+ else
+ self.principal_type == instance_or_klass.class.name and (self.principal_id.to_s == instance_or_klass.send(instance_or_klass.class.primary_key).to_s or self.principal_id == nil)
+ end
+ end
+
+ def permissionable_match?(instance_or_klass)
+ if instance_or_klass.is_a? Class
+ self.permissionable_type == instance_or_klass.name
+ else
+ self.permissionable_type == instance_or_klass.class.name and (self.permissionable_id.to_s == instance_or_klass.send(instance_or_klass.class.primary_key).to_s or self.permissionable_id == nil)
+ end
+ end
+
# Provides a basic description of the role.
def describe
prefix = ""
View
30 app/models/sanction/role/definition.rb
@@ -66,11 +66,41 @@ def self.with_permission(permission_name)
(roles_by_permission[permission_name] || []) + (wildcard_roles || [])
end
+ def self.process_role_or_permission_names_for_permissionable(permissionable, *role_or_permission_names)
+ role_or_permission_names.map do |role_or_permission|
+ roles_to_look_for = []
+ potential_permission_to_roles = Sanction::Role::Definition.permission_to_roles_for_permissionable(role_or_permission, permissionable)
+ roles_to_look_for << potential_permission_to_roles.map(&:name) unless potential_permission_to_roles.blank?
+
+ # Globals are removed from permissionable candidates
+ potential_roles = Sanction::Role::Definition.with(role_or_permission) & (Sanction::Role::Definition.over(permissionable) | Sanction::Role::Definition.globals)
+ roles_to_look_for << potential_roles.map(&:name) unless potential_roles.blank?
+
+ roles_to_look_for << role_or_permission if roles_to_look_for.blank?
+ roles_to_look_for
+ end.flatten.uniq
+ end
+
+ def self.process_role_or_permission_names_for_principal(principal, *role_or_permission_names)
+ role_or_permission_names.map do |role_or_permission|
+ roles_to_look_for = []
+ potential_permission_to_roles = Sanction::Role::Definition.permission_to_roles_for_principal(role_or_permission, principal)
+ roles_to_look_for << potential_permission_to_roles.map(&:name) unless potential_permission_to_roles.blank?
+
+ potential_roles = Sanction::Role::Definition.with(role_or_permission) & Sanction::Role::Definition.for(principal)
+ roles_to_look_for << potential_roles.map(&:name) unless potential_roles.blank?
+
+ roles_to_look_for << role_or_permission if roles_to_look_for.blank?
+ roles_to_look_for
+ end.flatten.uniq
+ end
+
def self.permission_to_roles_for_principal(permission_name, principal)
self.with_permission(permission_name) & self.for(principal)
end
def self.permission_to_roles_for_permissionable(permission_name, permissionable)
+ # Globals are removed from permissionable candidates
self.with_permission(permission_name) & (self.over(permissionable) | self.globals)
end
View
3 changelog
@@ -0,0 +1,3 @@
+1.2.0
+* Brings preloading of roles as an option. Person.find(:all, :preload_roles => true)
+* Uniformly treats class parameters across API, including *_all? methods.
View
1 install.rb
@@ -1 +0,0 @@
-# Install hook code here
View
92 lib/sanction/extensions/preload.rb
@@ -0,0 +1,92 @@
+module Sanction
+ module Extensions
+ module Preload
+ PRELOAD_ROLES = :preload_roles
+ PRELOAD_PRINCIPAL_ROLES = :preload_principal_roles
+ PRELOAD_PERMISSIONABLE_ROLES = :preload_permissionable_roles
+ PRELOAD_OPTIONS = [PRELOAD_ROLES, PRELOAD_PRINCIPAL_ROLES, PRELOAD_PERMISSIONABLE_ROLES]
+
+ def find(*args)
+ if args.last.respond_to? :keys and !(args.last.keys & PRELOAD_OPTIONS).blank?
+ preload = process_preload_options(args.last)
+ results = super
+
+ if preload[:roles] == true
+ preload_roles_for(results)
+ else
+ if preload[:principal_roles] == true
+ preload_principal_roles_for(results)
+ end
+
+ if preload[:permissionable_roles] == true
+ preload_permissionable_roles_for(results)
+ end
+ end
+
+ results
+ else
+ super
+ end
+ end
+
+ def process_preload_options(options = {})
+ preload = Hash.new(false)
+
+ if options.respond_to? :keys
+ if options.keys.include? PRELOAD_ROLES
+ preload[:roles] = options.delete(PRELOAD_ROLES)
+ end
+
+ if options.keys.include? PRELOAD_PRINCIPAL_ROLES
+ preload[:principal_roles] = options.delete(PRELOAD_PRINCIPAL_ROLES)
+ end
+
+ if options.keys.include? PRELOAD_PERMISSIONABLE_ROLES
+ preload[:permissionable_roles] = options.delete(PRELOAD_PERMISSIONABLE_ROLES)
+ end
+ end
+
+ preload
+ end
+
+ def preload_roles_for(results)
+ preload_principal_roles_for(results)
+ preload_permissionable_roles_for(results)
+ end
+
+ def preload_principal_roles_for(results)
+ if self.respond_to? :is_a_principal? and self.is_a_principal?
+ roles = Sanction::Role.for(*results)
+
+ if results.respond_to? :each
+ results.each do |result|
+ result.principal_roles = roles.select {|x| x.principal_match?(result)}
+ result.principal_roles_loaded
+ end
+ elsif results
+ results.principal_roles = roles.select {|x| x.principal_match?(results)}
+ results.principal_roles_loaded
+ end
+ end
+ results
+ end
+
+ def preload_permissionable_roles_for(results)
+ if self.respond_to? :is_a_permissionable? and self.is_a_permissionable?
+ roles = Sanction::Role.over(*results)
+
+ if results.respond_to? :each
+ results.each do |result|
+ result.permissionable_roles = roles.select {|x| x.permissionable_match?(result)}
+ result.permissionable_roles_loaded
+ end
+ elsif results
+ results.permissionable_roles = roles.select {|x| x.permissionable_match?(results)}
+ results.permissionable_roles_loaded
+ end
+ end
+ results
+ end
+ end
+ end
+end
View
5 lib/sanction/permissionable.rb
@@ -2,9 +2,10 @@
module Sanction
module Permissionable
ROLE_ALIAS = "sanction_permissionable_role_query"
-
def self.included(base)
- base.extend(Sanction::Permissionable::Base)
+ base.extend Sanction::Permissionable::Base
+ base.extend Sanction::Extensions::Preload
+
base.send(:include, Sanction::Permissionable::With)
base.send(:include, Sanction::Permissionable::For)
View
18 lib/sanction/permissionable/base.rb
@@ -4,13 +4,29 @@ module Base
def self.extended(base)
base.class_eval %q{
def permissionable_roles
- Sanction::Role.over(self)
+ @permissionable_roles ||= Sanction::Role.over(self)
+ end
+
+ def permissionable_roles=(permissionable_roles)
+ @permissionable_roles = permissionable_roles
+ end
+
+ def permissionable_roles_loaded?
+ @permissionable_roles_loaded ||= false
+ end
+
+ def permissionable_roles_loaded
+ @permissionable_roles_loaded = true
end
def self.permissionable_roles
Sanction::Role.over(self)
end
+ def self.is_a_permissionable?
+ true
+ end
+
has_many :specific_permissionable_roles, :as => :permissionable, :class_name => "Sanction::Role", :dependent => :destroy
}
View
50 lib/sanction/permissionable/for.rb
@@ -26,19 +26,6 @@ def self.extended(base)
{:conditions => conditions}
end
}
- base.named_scope :for_all_single_argument, lambda {|arg|
- if arg == Sanction::Role::Definition::ANY_TOKEN
- {:conditions => ["#{ROLE_ALIAS}.principal_type IS NOT NULL"]}
- else
- raise Sanction::Role::Error::UnknownPrincipal.new("Unknown principal: #{arg}") unless Sanction::Role::Definition.valid_principal? ar
-
- if arg.is_a? Class
- {:conditions => ["#{ROLE_ALIAS}.principal_type = ? AND #{ROLE_ALIAS}.principal_id IS NULL", arg.name.to_s]}
- else
- {:conditions => ["#{ROLE_ALIAS}.principal_type = ? AND (#{ROLE_ALIAS}.principal_id = ? OR #{ROLE_ALIAS}.principal_id IS NULL)", arg.class.name.to_s, arg.id]}
- end
- end
- }
end
def for(*args)
@@ -50,30 +37,41 @@ def for?(*args)
end
def for_all?(*args)
- result = nil
- args.each do |arg|
- if result.nil?
- result = self.for_all_single_argument(arg)
- else
- result = result & self.for_all_single_argument(arg)
- end
- end
-
- !result.blank?
+ !args.map {|a| self.for(a)}.inject(&:&).blank?
end
end
module InstanceMethods
def for(*args)
- self.class.as_permissionable(self).for_scope_method(*args)
+ if self.permissionable_roles_loaded?
+ found_for = false
+
+ if args.include? Sanction::Role::Definition::ANY_TOKEN
+ found_for = true if self.permissionable_roles.detect {|r| r.principal_type != nil}
+ else
+ args.each do |a|
+ raise Sanction::Role::Error::UnknownPrincipal.new("Unknown principal: #{a}") unless Sanction::Role::Definition.valid_principal? a
+
+ found_for = true if self.permissionable_roles.detect {|r| r.principal_match? a}
+ end
+ end
+
+ if found_for
+ Sanction::Result::SingleArray.construct(self)
+ else
+ Sanction::Result::BlankArray.construct(self)
+ end
+ else
+ self.class.as_permissionable(self).for_scope_method(*args)
+ end
end
def for?(*args)
!self.for(*args).blank?
end
-
+
def for_all?(*args)
- !self.class.as_permissionable(self).for_all?(*args)
+ !args.map {|a| self.for(a)}.inject(&:&).blank?
end
end
end
View
34 lib/sanction/permissionable/with.rb
@@ -11,19 +11,7 @@ def self.extended(base)
if role_names.include? Sanction::Role::Definition::ANY_TOKEN
{:conditions => [ROLE_ALIAS + ".name IS NOT NULL"]} if role_names.include? :any
else
- role_names.map! do |role_or_permission|
- roles_to_look_for = []
- potential_permission_to_roles = Sanction::Role::Definition.permission_to_roles_for_permissionable(role_or_permission, base)
- roles_to_look_for << potential_permission_to_roles.map(&:name) unless potential_permission_to_roles.blank?
-
- potential_roles = Sanction::Role::Definition.with(role_or_permission) & (Sanction::Role::Definition.over(base) | Sanction::Role::Definition.globals)
- roles_to_look_for << potential_roles.map(&:name) unless potential_roles.blank?
-
- roles_to_look_for << role_or_permission if roles_to_look_for.blank?
- roles_to_look_for
- end
- role_names.flatten!
- role_names.uniq!
+ role_names = Sanction::Role::Definition.process_role_or_permission_names_for_permissionable(base, *role_names)
conditions = role_names.map {|r| base.merge_conditions(["#{ROLE_ALIAS}.name = ?", r.to_s])}.join(" OR ")
{:conditions => conditions}
@@ -55,15 +43,31 @@ def with_all?(*role_names)
module InstanceMethods
def with(*role_names)
- self.class.as_permissionable(self).with_scope_method(*role_names)
+ if self.permissionable_roles_loaded?
+ blank_result = true
+ if role_names.include? Sanction::Role::Definition::ANY_TOKEN
+ blank_result = false unless self.permissionable_roles.blank?
+ else
+ p_roles = Sanction::Role::Definition.process_role_or_permission_names_for_permissionable(self.class, *role_names).map(&:to_sym)
+ blank_result = false unless self.permissionable_roles.detect { |r| p_roles.include? r.name.to_sym }.blank?
+ end
+
+ if blank_result
+ Sanction::Result::BlankArray.construct(self)
+ else
+ Sanction::Result::SingleArray.construct(self)
+ end
+ else
+ self.class.as_permissionable(self).with_scope_method(*role_names)
+ end
end
def with?(*role_names)
!with(*role_names).blank?
end
def with_all?(*role_names)
- !self.class.as_permissionable(self).with_all?(*role_names)
+ !role_names.map {|r| with(r)}.inject(&:&).blank?
end
end
end
View
2 lib/sanction/principal.rb
@@ -4,6 +4,8 @@ module Principal
ROLE_ALIAS = "sanction_principal_role_query"
def self.included(base)
base.extend Sanction::Principal::Base
+ base.extend Sanction::Extensions::Preload
+
base.send(:include, Sanction::Principal::Has)
base.send(:include, Sanction::Principal::Over)
View
22 lib/sanction/principal/base.rb
@@ -2,14 +2,30 @@ module Sanction
module Principal
module Base
def self.extended(base)
- base.class_eval %q{
+ base.class_eval %Q{
def principal_roles
- Sanction::Role.for(self)
+ @principal_roles ||= Sanction::Role.for(self)
end
-
+
+ def principal_roles=(principal_roles)
+ @principal_roles = principal_roles
+ end
+
+ def principal_roles_loaded?
+ @principal_roles_loaded ||= false
+ end
+
+ def principal_roles_loaded
+ @principal_roles_loaded = true
+ end
+
def self.principal_roles
Sanction::Role.for(self)
end
+
+ def self.is_a_principal?
+ true
+ end
has_many :specific_principal_roles, :as => :principal, :class_name => "Sanction::Role", :dependent => :destroy
}
View
34 lib/sanction/principal/has.rb
@@ -12,19 +12,7 @@ def self.extended(base)
if role_names.include? Sanction::Role::Definition::ANY_TOKEN
{:conditions => [ROLE_ALIAS + ".name IS NOT NULL"]}
else
- role_names.map! do |role_or_permission|
- roles_to_look_for = []
- potential_permission_to_roles = Sanction::Role::Definition.permission_to_roles_for_principal(role_or_permission, base)
- roles_to_look_for << potential_permission_to_roles.map(&:name) unless potential_permission_to_roles.blank?
-
- potential_roles = Sanction::Role::Definition.with(role_or_permission) & Sanction::Role::Definition.for(base)
- roles_to_look_for << potential_roles.map(&:name) unless potential_roles.blank?
-
- roles_to_look_for << role_or_permission if roles_to_look_for.blank?
- roles_to_look_for
- end
- role_names.flatten!
- role_names.uniq!
+ role_names = Sanction::Role::Definition.process_role_or_permission_names_for_principal(base, *role_names)
conditions = role_names.map {|r| base.merge_conditions(["#{ROLE_ALIAS}.name = ?", r.to_s])}.join(" OR ")
{:conditions => conditions}
@@ -56,15 +44,31 @@ def has_all?(*role_names)
module InstanceMethods
def has(*role_names)
- self.class.as_principal(self).has_scope_method(*role_names)
+ if self.principal_roles_loaded?
+ blank_result = true
+ if role_names.include? Sanction::Role::Definition::ANY_TOKEN
+ blank_result = false unless self.principal_roles.blank?
+ else
+ p_roles = Sanction::Role::Definition.process_role_or_permission_names_for_principal(self.class, *role_names).map(&:to_sym)
+ blank_result = false unless self.principal_roles.detect { |r| p_roles.include? r.name.to_sym }.blank?
+ end
+
+ if blank_result
+ Sanction::Result::BlankArray.construct(self)
+ else
+ Sanction::Result::SingleArray.construct(self)
+ end
+ else
+ self.class.as_principal(self).has_scope_method(*role_names)
+ end
end
def has?(*role_names)
!has(*role_names).blank?
end
def has_all?(*role_names)
- self.class.as_principal(self).has_all?(*role_names)
+ !role_names.map {|r| has(r)}.inject(&:&).blank?
end
end
end
View
50 lib/sanction/principal/over.rb
@@ -8,15 +8,35 @@ def self.included(base)
module InstanceMethods
def over(*args)
- self.class.as_principal(self).over_scope_method(*args)
+ if self.principal_roles_loaded?
+ found_over = false
+
+ if args.include? Sanction::Role::Definition::ANY_TOKEN
+ found_over = true if self.principal_roles.detect {|r| r.permissionable_type != nil}
+ else
+ args.each do |a|
+ raise Sanction::Role::Error::UnknownPermissionable.new("Unknown permissionable: #{a}") unless Sanction::Role::Definition.valid_permissionable? a
+
+ found_over = true if self.principal_roles.detect {|r| r.permissionable_match? a}
+ end
+ end
+
+ if found_over
+ Sanction::Result::SingleArray.construct(self)
+ else
+ Sanction::Result::BlankArray.construct(self)
+ end
+ else
+ self.class.as_principal(self).over_scope_method(*args)
+ end
end
def over?(*args)
!over(*args).blank?
end
def over_all?(*args)
- self.class.as_principal(self).over_all?(*args)
+ !args.map {|a| over(a)}.inject(&:&).blank?
end
end
@@ -31,7 +51,7 @@ def self.extended(base)
conds = []
args.each do |arg|
if arg.is_a? Class
- conds << ["#{ROLE_ALIAS}.permissionable_type = ?", arg.name.to_s] # Need id = nil here?
+ conds << ["#{ROLE_ALIAS}.permissionable_type = ?", arg.name.to_s]
else
conds << ["#{ROLE_ALIAS}.permissionable_type = ? AND (#{ROLE_ALIAS}.permissionable_id = ? OR #{ROLE_ALIAS}.permissionable_id IS NULL)", arg.class.name.to_s, arg.id]
end
@@ -40,19 +60,6 @@ def self.extended(base)
{:conditions => conditions}
end
}
- base.named_scope :over_all_single_argument, lambda {|arg|
- if arg == Sanction::Role::Definition::ANY_TOKEN
- {:conditions => ["#{ROLE_ALIAS}.permissionable_type IS NOT NULL"]}
- else
- raise Sanction::Role::Error::UnknownPermissionable.new("Unknown permissionable: #{arg}") unless Sanction::Role::Definition.valid_permissionable? arg
-
- if arg.is_a? Class
- {:conditions => ["#{ROLE_ALIAS}.permissionable_type = ? AND #{ROLE_ALIAS}.permissionable_id IS NULL", arg.name.to_s]}
- else
- {:conditions => ["#{ROLE_ALIAS}.permissionable_type = ? AND (#{ROLE_ALIAS}.permissionable_id = ? OR #{ROLE_ALIAS}.permissionable_id IS NULL)", arg.class.name.to_s, arg.id]}
- end
- end
- }
end
def over(*args)
@@ -64,16 +71,7 @@ def over?(*args)
end
def over_all?(*args)
- result = nil
- args.each do |arg|
- if result.nil?
- result = self.over_all_single_argument(arg)
- else
- result = result & self.over_all_single_argument(arg)
- end
- end
-
- !result.blank?
+ !args.map {|a| over(a)}.inject(&:&).blank?
end
end
end
View
34 lib/sanction/result/blank_array.rb
@@ -0,0 +1,34 @@
+module Sanction
+ module Result
+ class BlankArray
+ def self.construct(decoy)
+ @decoy = decoy
+
+ a = []
+ a.instance_variable_set(:@decoy, @decoy)
+ (class << a; self; end).send(:include, MethodMissing)
+ a
+ end
+
+ module MethodMissing
+ def method_missing(m, *args)
+ if @decoy.class.respond_to? :is_a_principal? and @decoy.class.is_a_principal?
+ if [:has, :over].include? m
+ Sanction::Result::BlankArray.construct(@decoy)
+ elsif [:has?, :has_all?, :over?, :over_all?].include? m
+ false
+ end
+ elsif @decoy.class.respond_to? :is_a_permissionable? and @decoy.class.is_a_permissionable?
+ if [:with, :for].include? m
+ Sanction::Result::BlankArray.construct(@decoy)
+ elsif [:with?, :with_all?, :for?, :for_all?].include? m
+ false
+ end
+ else
+ @decoy.send(m, *args)
+ end
+ end
+ end
+ end
+ end
+end
View
18 lib/sanction/result/single_array.rb
@@ -0,0 +1,18 @@
+module Sanction
+ module Result
+ class SingleArray
+ def self.construct(decoy)
+ a = [decoy]
+ a.instance_variable_set(:@decoy, decoy)
+ (class << a; self; end).send(:include, MethodMissing)
+ a
+ end
+
+ module MethodMissing
+ def method_missing(m, *args)
+ @decoy.send(m, *args)
+ end
+ end
+ end
+ end
+end
View
4 lib/sanction/version.rb
@@ -1,8 +1,8 @@
module Sanction
module Version
MAJOR = 1
- MINOR = 1
- TINY = 5
+ MINOR = 2
+ TINY = 0
STRING = [MAJOR, MINOR, TINY].join('.')
end
View
150 test/unit/sanction_test.rb
@@ -494,4 +494,154 @@ def test_principal_roles_and_permissionable_roles_assoc
magazine.destroy
person.destroy
end
+
+ def test_eager_loading_mechanism
+ person = Person.first
+ magazine = Magazine.first
+
+ person.grant(:editor, Magazine)
+
+ p = Person.find(:first, :conditions => ["unique_id = ?", person.unique_id], :preload_roles => true)
+ m = Magazine.find(:first, :conditions => ["id = ?", magazine.id], :preload_roles => true)
+
+ assert p.principal_roles_loaded?
+
+ person.revoke(:editor, Magazine)
+ person.reload
+
+ assert !person.has?(:editor)
+ assert !person.has(:editor).over?(Magazine)
+ assert p.has?(:editor)
+ assert p.has(:editor).over?(Magazine)
+ assert !magazine.with?(:editor)
+ assert !magazine.for(person).with?(:editor)
+ assert m.with?(:editor)
+ assert m.for?(person)
+ assert m.for(person).with?(:editor)
+ end
+
+ def test_eager_loading_with_permissions
+ person = Person.first
+ magazine = Magazine.first
+
+ person.grant(:owner, Magazine)
+
+ p = Person.find(:first, :conditions => ["unique_id = ?", person.unique_id], :preload_roles => true)
+ m = Magazine.find(:first, :conditions => ["id = ?", magazine.id], :preload_roles => true)
+
+ assert p.principal_roles_loaded?
+ assert m.permissionable_roles_loaded?
+
+ person.revoke(:owner, Magazine)
+
+ assert !person.has?(:can_edit)
+ assert !person.has(:editor).over?(Magazine)
+ assert p.has?(:can_edit)
+ assert p.has(:editor).over?(Magazine)
+ assert !magazine.with?(:can_edit)
+ assert !magazine.for(Person).with?(:can_edit)
+ assert m.with?(:can_edit)
+ assert m.with?(:any)
+ assert m.for?(:any)
+ assert m.for(:any).with?(:can_edit)
+ assert m.for(Person).with?(:can_edit)
+ end
+
+ def test_blank_result_from_eager_loading
+ person = Person.first
+
+ person.grant(:owner, Magazine)
+
+ p = Person.find(:first, :conditions => ["unique_id = ?", person.unique_id], :preload_roles => true)
+
+ person.revoke(:owner, Magazine)
+
+ assert p.has?(:can_edit)
+ assert !p.has?(:non_permission)
+ assert !p.has(:non_permission).over?(Magazine)
+ end
+
+ def test_single_result_from_eager_loading
+ person = Person.first
+ person.grant(:editor, Magazine)
+
+ p = Person.first(:preload_roles => true)
+
+ assert p.has?(:any) == person.has?(:any)
+ assert (p.has(:any) - person.has(:any)).size == 0
+
+ person.revoke(:editor, Magazine)
+ end
+
+ def test_iteration_of_preloaded_roles
+ Person.grant(:reader, Magazine)
+
+ people = Person.find(:all, :preload_roles => true)
+
+ Person.revoke(:reader, Magazine)
+
+ people.each do |p|
+ assert p.has?(:reader)
+ assert p.has(:reader).over?(Magazine)
+ assert !p.has?(:some_non_role)
+ assert !p.has(:some_non_role).over?(:any)
+ assert !p.has(:some_non_role).over?(Magazine)
+ end
+
+ assert !Person.first.has?(:reader)
+ end
+
+ def test_has_all_with_preloaded_roles
+ Person.grant(:reader, Magazine)
+ Person.grant(:editor, Magazine)
+
+ person = Person.first :preload_roles => true
+
+ Person.revoke(:reader, Magazine)
+ Person.revoke(:editor, Magazine)
+
+ assert person.has_all?(:reader, :editor)
+ assert !Person.first.has_all?(:reader, :editor)
+ assert !person.has_all?(:reader, :editor, :owner)
+ end
+
+ def test_with_all_with_preloaded_roles
+ Person.grant(:reader, Magazine)
+ Person.grant(:editor, Magazine)
+
+ magazine = Magazine.first :preload_roles => true
+
+ Person.revoke(:reader, Magazine)
+ Person.revoke(:editor, Magazine)
+
+ assert magazine.with_all?(:reader, :editor)
+ assert !Magazine.first.with_all?(:reader, :editor)
+ assert !magazine.with_all?(:reader, :editor, :owner)
+ end
+
+ def test_over_all_with_prelaoded_roles
+ Person.grant(:reader, Magazine)
+
+ person = Person.first :preload_roles => true
+
+ assert Person.first.over_all?(Magazine.first, Magazine.last)
+
+ Person.revoke(:reader, Magazine)
+
+ assert person.over_all?(Magazine.first, Magazine.last)
+ assert !Person.first.over_all?(Magazine.first, Magazine.last)
+ end
+
+ def test_for_all_with_preloaded_roles
+ Person.grant(:reader, Magazine)
+
+ magazine = Magazine.first :preload_roles => true
+
+ assert Magazine.first.for_all?(Person.first, Person.last)
+
+ Person.revoke(:reader, Magazine)
+
+ assert magazine.for_all?(Person.first, Person.last)
+ assert !Magazine.first.for_all?(Person.first, Person.last)
+ end
end
View
1 uninstall.rb
@@ -1 +0,0 @@
-# Uninstall hook code here

0 comments on commit dfb2e5a

Please sign in to comment.