renaming CanDefinition to Rule

This commit is contained in:
Ryan Bates 2010-12-21 10:41:55 -08:00
parent a6959c0ab2
commit 37c149182c
8 changed files with 59 additions and 59 deletions

View File

@ -1,5 +1,5 @@
require 'cancan/ability' require 'cancan/ability'
require 'cancan/can_definition' require 'cancan/rule'
require 'cancan/controller_resource' require 'cancan/controller_resource'
require 'cancan/controller_additions' require 'cancan/controller_additions'
require 'cancan/active_record_additions' require 'cancan/active_record_additions'

View File

@ -54,8 +54,8 @@ module CanCan
# #
# Also see the RSpec Matchers to aid in testing. # Also see the RSpec Matchers to aid in testing.
def can?(action, subject, *extra_args) def can?(action, subject, *extra_args)
match = relevant_can_definitions_for_match(action, subject).detect do |can_definition| match = relevant_rules_for_match(action, subject).detect do |rule|
can_definition.matches_conditions?(action, subject, extra_args) rule.matches_conditions?(action, subject, extra_args)
end end
match ? match.base_behavior : false match ? match.base_behavior : false
end end
@ -122,7 +122,7 @@ module CanCan
# end # end
# #
def can(action = nil, subject = nil, conditions = nil, &block) def can(action = nil, subject = nil, conditions = nil, &block)
can_definitions << CanDefinition.new(true, action, subject, conditions, block) rules << Rule.new(true, action, subject, conditions, block)
end end
# Defines an ability which cannot be done. Accepts the same arguments as "can". # Defines an ability which cannot be done. Accepts the same arguments as "can".
@ -138,7 +138,7 @@ module CanCan
# end # end
# #
def cannot(action = nil, subject = nil, conditions = nil, &block) def cannot(action = nil, subject = nil, conditions = nil, &block)
can_definitions << CanDefinition.new(false, action, subject, conditions, block) rules << Rule.new(false, action, subject, conditions, block)
end end
# Alias one or more actions into another one. # Alias one or more actions into another one.
@ -187,10 +187,10 @@ module CanCan
end end
# Returns a CanCan::Query instance to help generate database queries based on the ability. # Returns a CanCan::Query instance to help generate database queries based on the ability.
# If any relevant can definitions use a block then an exception will be raised because an # If any relevant rules use a block then an exception will be raised because an
# SQL query cannot be generated from blocks of code. # SQL query cannot be generated from blocks of code.
def query(action, subject) def query(action, subject)
Query.new(subject, relevant_can_definitions_for_query(action, subject)) Query.new(subject, relevant_rules_for_query(action, subject))
end end
# See ControllerAdditions#authorize! for documentation. # See ControllerAdditions#authorize! for documentation.
@ -215,18 +215,18 @@ module CanCan
def attributes_for(action, subject) def attributes_for(action, subject)
attributes = {} attributes = {}
relevant_can_definitions(action, subject).map do |can_definition| relevant_rules(action, subject).map do |rule|
attributes.merge!(can_definition.attributes_from_conditions) if can_definition.base_behavior attributes.merge!(rule.attributes_from_conditions) if rule.base_behavior
end end
attributes attributes
end end
def has_block?(action, subject) def has_block?(action, subject)
relevant_can_definitions(action, subject).any?(&:only_block?) relevant_rules(action, subject).any?(&:only_block?)
end end
def has_raw_sql?(action, subject) def has_raw_sql?(action, subject)
relevant_can_definitions(action, subject).any?(&:only_raw_sql?) relevant_rules(action, subject).any?(&:only_raw_sql?)
end end
private private
@ -259,30 +259,30 @@ module CanCan
results results
end end
def can_definitions def rules
@can_definitions ||= [] @rules ||= []
end end
# Returns an array of CanDefinition instances which match the action and subject # Returns an array of Rule instances which match the action and subject
# This does not take into consideration any hash conditions or block statements # This does not take into consideration any hash conditions or block statements
def relevant_can_definitions(action, subject) def relevant_rules(action, subject)
can_definitions.reverse.select do |can_definition| rules.reverse.select do |rule|
can_definition.expanded_actions = expand_actions(can_definition.actions) rule.expanded_actions = expand_actions(rule.actions)
can_definition.relevant? action, subject rule.relevant? action, subject
end end
end end
def relevant_can_definitions_for_match(action, subject) def relevant_rules_for_match(action, subject)
relevant_can_definitions(action, subject).each do |can_definition| relevant_rules(action, subject).each do |rule|
if can_definition.only_raw_sql? if rule.only_raw_sql?
raise Error, "The can? and cannot? call cannot be used with a raw sql 'can' definition. The checking code cannot be determined for #{action.inspect} #{subject.inspect}" raise Error, "The can? and cannot? call cannot be used with a raw sql 'can' definition. The checking code cannot be determined for #{action.inspect} #{subject.inspect}"
end end
end end
end end
def relevant_can_definitions_for_query(action, subject) def relevant_rules_for_query(action, subject)
relevant_can_definitions(action, subject).each do |can_definition| relevant_rules(action, subject).each do |rule|
if can_definition.only_block? if rule.only_block?
raise Error, "The accessible_by call cannot be used with a block 'can' definition. The SQL cannot be determined for #{action.inspect} #{subject.inspect}" raise Error, "The accessible_by call cannot be used with a block 'can' definition. The SQL cannot be determined for #{action.inspect} #{subject.inspect}"
end end
end end

View File

@ -12,21 +12,21 @@ module CanCan
end end
def query_with_mongoid_support(action, subject) def query_with_mongoid_support(action, subject)
MongoidQuery.new(subject, relevant_can_definitions_for_query(action, subject)) MongoidQuery.new(subject, relevant_rules_for_query(action, subject))
end end
end end
class MongoidQuery class MongoidQuery
def initialize(sanitizer, can_definitions) def initialize(sanitizer, rules)
@sanitizer = sanitizer @sanitizer = sanitizer
@can_definitions = can_definitions @rules = rules
end end
def conditions def conditions
if @can_definitions.size == 0 if @rules.size == 0
false_query false_query
else else
@can_definitions.first.instance_variable_get(:@conditions) @rules.first.instance_variable_get(:@conditions)
end end
end end
@ -45,7 +45,7 @@ module CanCan
# => true # => true
# {}.all?{|a| a != 5} # {}.all?{|a| a != 5}
# => true # => true
class CanDefinition class Rule
def matches_conditions_hash_with_mongoid_subject?(subject, conditions = @conditions) def matches_conditions_hash_with_mongoid_subject?(subject, conditions = @conditions)
if subject.class.include?(Mongoid::Document) && conditions.any?{|k,v| !k.kind_of?(Symbol)} if subject.class.include?(Mongoid::Document) && conditions.any?{|k,v| !k.kind_of?(Symbol)}
if conditions.empty? if conditions.empty?

View File

@ -3,9 +3,9 @@ module CanCan
# Generates the sql conditions and association joins for use in ActiveRecord queries. # Generates the sql conditions and association joins for use in ActiveRecord queries.
# Normally you will not use this class directly, but instead through ActiveRecordAdditions#accessible_by. # Normally you will not use this class directly, but instead through ActiveRecordAdditions#accessible_by.
class Query class Query
def initialize(sanitizer, can_definitions) def initialize(sanitizer, rules)
@sanitizer = sanitizer @sanitizer = sanitizer
@can_definitions = can_definitions @rules = rules
end end
# Returns conditions intended to be used inside a database query. Normally you will not call this # Returns conditions intended to be used inside a database query. Normally you will not call this
@ -24,12 +24,12 @@ module CanCan
# query(:manage, User).conditions # => "not (self_managed = 't') AND ((manager_id = 1) OR (id = 1))" # query(:manage, User).conditions # => "not (self_managed = 't') AND ((manager_id = 1) OR (id = 1))"
# #
def conditions def conditions
if @can_definitions.size == 1 && @can_definitions.first.base_behavior if @rules.size == 1 && @rules.first.base_behavior
# Return the conditions directly if there's just one definition # Return the conditions directly if there's just one definition
@can_definitions.first.tableized_conditions @rules.first.tableized_conditions
else else
@can_definitions.reverse.inject(false_sql) do |sql, can_definition| @rules.reverse.inject(false_sql) do |sql, rule|
merge_conditions(sql, can_definition.tableized_conditions, can_definition.base_behavior) merge_conditions(sql, rule.tableized_conditions, rule.base_behavior)
end end
end end
end end
@ -38,8 +38,8 @@ module CanCan
# See ActiveRecordAdditions#accessible_by for use in Active Record. # See ActiveRecordAdditions#accessible_by for use in Active Record.
def joins def joins
joins_hash = {} joins_hash = {}
@can_definitions.each do |can_definition| @rules.each do |rule|
merge_joins(joins_hash, can_definition.associations_hash) merge_joins(joins_hash, rule.associations_hash)
end end
clean_joins(joins_hash) unless joins_hash.empty? clean_joins(joins_hash) unless joins_hash.empty?
end end

View File

@ -2,7 +2,7 @@ module CanCan
# This class is used internally and should only be called through Ability. # This class is used internally and should only be called through Ability.
# it holds the information about a "can" call made on Ability and provides # it holds the information about a "can" call made on Ability and provides
# helpful methods to determine permission checking and conditions hash generation. # helpful methods to determine permission checking and conditions hash generation.
class CanDefinition # :nodoc: class Rule # :nodoc:
attr_reader :base_behavior, :actions attr_reader :base_behavior, :actions
attr_writer :expanded_actions attr_writer :expanded_actions

View File

@ -32,7 +32,7 @@ describe CanCan::Ability do
@ability.can?(:read, Symbol).should be_true @ability.can?(:read, Symbol).should be_true
end end
it "should pass to previous can definition, if block returns false or nil" do it "should pass to previous rule, if block returns false or nil" do
@ability.can :read, Symbol @ability.can :read, Symbol
@ability.can :read, Integer do |i| @ability.can :read, Integer do |i|
i < 5 i < 5
@ -144,7 +144,7 @@ describe CanCan::Ability do
@ability.can?(:update, 123).should be_false @ability.can?(:update, 123).should be_false
end end
it "should support custom objects in the can definition" do it "should support custom objects in the rule" do
@ability.can :read, :stats @ability.can :read, :stats
@ability.can?(:read, :stats).should be_true @ability.can?(:read, :stats).should be_true
@ability.can?(:update, :stats).should be_false @ability.can?(:update, :stats).should be_false
@ -165,7 +165,7 @@ describe CanCan::Ability do
@ability.can?(:read, 123).should be_false @ability.can?(:read, 123).should be_false
end end
it "should pass to previous can definition, if block returns false or nil" do it "should pass to previous rule, if block returns false or nil" do
@ability.can :read, :all @ability.can :read, :all
@ability.cannot :read, Integer do |int| @ability.cannot :read, Integer do |int|
int > 10 ? nil : ( int > 5 ) int > 10 ? nil : ( int > 5 )

View File

@ -15,19 +15,19 @@ describe CanCan::Query do
@ability.query(:read, Project).conditions.should == { :blocked => false, :user_id => 1 } @ability.query(:read, Project).conditions.should == { :blocked => false, :user_id => 1 }
end end
it "should merge multiple can definitions into single SQL string joining with OR" do it "should merge multiple rules into single SQL string joining with OR" do
@ability.can :read, Project, :blocked => false @ability.can :read, Project, :blocked => false
@ability.can :read, Project, :admin => true @ability.can :read, Project, :admin => true
@ability.query(:read, Project).conditions.should == "(admin=true) OR (blocked=false)" @ability.query(:read, Project).conditions.should == "(admin=true) OR (blocked=false)"
end end
it "should merge multiple can definitions into single SQL string joining with OR and AND" do it "should merge multiple rules into single SQL string joining with OR and AND" do
@ability.can :read, Project, :blocked => false, :active => true @ability.can :read, Project, :blocked => false, :active => true
@ability.can :read, Project, :admin => true @ability.can :read, Project, :admin => true
@ability.query(:read, Project).conditions.should orderlessly_match("(blocked=false AND active=true) OR (admin=true)") @ability.query(:read, Project).conditions.should orderlessly_match("(blocked=false AND active=true) OR (admin=true)")
end end
it "should merge multiple can definitions into single SQL string joining with OR and AND" do it "should merge multiple rules into single SQL string joining with OR and AND" do
@ability.can :read, Project, :blocked => false, :active => true @ability.can :read, Project, :blocked => false, :active => true
@ability.can :read, Project, :admin => true @ability.can :read, Project, :admin => true
@ability.query(:read, Project).conditions.should orderlessly_match("(blocked=false AND active=true) OR (admin=true)") @ability.query(:read, Project).conditions.should orderlessly_match("(blocked=false AND active=true) OR (admin=true)")
@ -77,7 +77,7 @@ describe CanCan::Query do
@ability.query(:read, Project).conditions.should == 'true=true' @ability.query(:read, Project).conditions.should == 'true=true'
end end
it "should have nil joins if no can definitions" do it "should have nil joins if no rules" do
@ability.query(:read, Project).joins.should be_nil @ability.query(:read, Project).joins.should be_nil
end end

View File

@ -1,57 +1,57 @@
require "spec_helper" require "spec_helper"
# Most of CanDefinition functionality is tested in Ability specs # Most of Rule functionality is tested in Ability specs
describe CanCan::CanDefinition do describe CanCan::Rule do
before(:each) do before(:each) do
@conditions = {} @conditions = {}
@can = CanCan::CanDefinition.new(true, :read, Integer, @conditions, nil) @rule = CanCan::Rule.new(true, :read, Integer, @conditions, nil)
end end
it "should return no association joins if none exist" do it "should return no association joins if none exist" do
@can.associations_hash.should == {} @rule.associations_hash.should == {}
end end
it "should return no association for joins if just attributes" do it "should return no association for joins if just attributes" do
@conditions[:foo] = :bar @conditions[:foo] = :bar
@can.associations_hash.should == {} @rule.associations_hash.should == {}
end end
it "should return single association for joins" do it "should return single association for joins" do
@conditions[:foo] = {:bar => 1} @conditions[:foo] = {:bar => 1}
@can.associations_hash.should == {:foo => {}} @rule.associations_hash.should == {:foo => {}}
end end
it "should return multiple associations for joins" do it "should return multiple associations for joins" do
@conditions[:foo] = {:bar => 1} @conditions[:foo] = {:bar => 1}
@conditions[:test] = {1 => 2} @conditions[:test] = {1 => 2}
@can.associations_hash.should == {:foo => {}, :test => {}} @rule.associations_hash.should == {:foo => {}, :test => {}}
end end
it "should return nested associations for joins" do it "should return nested associations for joins" do
@conditions[:foo] = {:bar => {1 => 2}} @conditions[:foo] = {:bar => {1 => 2}}
@can.associations_hash.should == {:foo => {:bar => {}}} @rule.associations_hash.should == {:foo => {:bar => {}}}
end end
it "should tableize correctly for absurdly complex permissions" do it "should tableize correctly for absurdly complex permissions" do
@conditions[:unit] = {:property=>{:landlord=>{:weasle_id=>560}}} @conditions[:unit] = {:property=>{:landlord=>{:weasle_id=>560}}}
@conditions[:test] = 1 @conditions[:test] = 1
@can.tableized_conditions.should == {:units => {:properties => {:landlords=>{:weasle_id=>560}}}, :test => 1} @rule.tableized_conditions.should == {:units => {:properties => {:landlords=>{:weasle_id=>560}}}, :test => 1}
end end
it "should tableize correctly for complex permissions" do it "should tableize correctly for complex permissions" do
@conditions[:unit] = {:property=>{:landlord_id=>560}} @conditions[:unit] = {:property=>{:landlord_id=>560}}
@conditions[:test] = 1 @conditions[:test] = 1
@can.tableized_conditions.should == {:units => {:properties => {:landlord_id=>560}}, :test => 1} @rule.tableized_conditions.should == {:units => {:properties => {:landlord_id=>560}}, :test => 1}
end end
it "should return table names in conditions for association joins" do it "should return table names in conditions for association joins" do
@conditions[:foo] = {:bar => 1} @conditions[:foo] = {:bar => 1}
@conditions[:test] = 1 @conditions[:test] = 1
@can.tableized_conditions.should == {:foos => {:bar => 1}, :test => 1} @rule.tableized_conditions.should == {:foos => {:bar => 1}, :test => 1}
end end
it "should return no association joins if conditions is nil" do it "should return no association joins if conditions is nil" do
can = CanCan::CanDefinition.new(true, :read, Integer, nil, nil) rule = CanCan::Rule.new(true, :read, Integer, nil, nil)
can.associations_hash.should == {} rule.associations_hash.should == {}
end end
end end