passing throw matching rules with not matching conditions
Main goal is to allow: cannot :manage, :all can :read, :all can :manage, User, :id=>user.id can :manage, User, :manager_id=>user.id Signed-off-by: Sokolov Yura <funny.falcon@gmail.com>
This commit is contained in:
		
							parent
							
								
									06296b0a40
								
							
						
					
					
						commit
						7d7d249182
					
				@ -49,8 +49,12 @@ module CanCan
 | 
				
			|||||||
    # 
 | 
					    # 
 | 
				
			||||||
    def can?(action, subject, *extra_args)
 | 
					    def can?(action, subject, *extra_args)
 | 
				
			||||||
      raise Error, "Nom nom nom. I eated it." if action == :has && subject == :cheezburger
 | 
					      raise Error, "Nom nom nom. I eated it." if action == :has && subject == :cheezburger
 | 
				
			||||||
      can_definition = matching_can_definition(action, subject)
 | 
					      matching_can_definition(action, subject) do |can_definition|
 | 
				
			||||||
      can_definition && can_definition.can?(action, subject, extra_args)
 | 
					        unless (can = can_definition.can?(action, subject, extra_args)) == :_NOT_MATCHED
 | 
				
			||||||
 | 
					          return can
 | 
				
			||||||
 | 
					        end
 | 
				
			||||||
 | 
					      end
 | 
				
			||||||
 | 
					      false
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    # Convenience method which works the same as "can?" but returns the opposite value.
 | 
					    # Convenience method which works the same as "can?" but returns the opposite value.
 | 
				
			||||||
@ -179,11 +183,15 @@ module CanCan
 | 
				
			|||||||
      @aliased_actions = {}
 | 
					      @aliased_actions = {}
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    # Returns a hash of conditions which match the given ability. This is useful if you need to generate a database
 | 
					    # Returns an array of arrays composing from desired action and hash of conditions which match the given ability.
 | 
				
			||||||
    # query based on the current ability.
 | 
					    # This is useful if you need to generate a database query based on the current ability.
 | 
				
			||||||
    # 
 | 
					    # 
 | 
				
			||||||
    #   can :read, Article, :visible => true
 | 
					    #   can :read, Article, :visible => true
 | 
				
			||||||
    #   conditions :read, Article # returns { :visible => true }
 | 
					    #   conditions :read, Article # returns [ [ true, { :visible => true } ] ]
 | 
				
			||||||
 | 
					    #
 | 
				
			||||||
 | 
					    #   can :read, Article, :visible => true
 | 
				
			||||||
 | 
					    #   cannot :read, Article, :blocked => true
 | 
				
			||||||
 | 
					    #   conditions :read, Article # returns [ [ false, { :blocked => true } ], [ true, { :visible => true } ] ]
 | 
				
			||||||
    # 
 | 
					    # 
 | 
				
			||||||
    # Normally you will not call this method directly, but instead go through ActiveRecordAdditions#accessible_by method.
 | 
					    # Normally you will not call this method directly, but instead go through ActiveRecordAdditions#accessible_by method.
 | 
				
			||||||
    # 
 | 
					    # 
 | 
				
			||||||
@ -191,22 +199,71 @@ module CanCan
 | 
				
			|||||||
    # If the ability is defined using a block then this will raise an exception since a hash of conditions cannot be
 | 
					    # If the ability is defined using a block then this will raise an exception since a hash of conditions cannot be
 | 
				
			||||||
    # determined from that.
 | 
					    # determined from that.
 | 
				
			||||||
    def conditions(action, subject)
 | 
					    def conditions(action, subject)
 | 
				
			||||||
      can_definition = matching_can_definition(action, subject)
 | 
					      matched = matching_can_definition(action, subject)
 | 
				
			||||||
      if can_definition
 | 
					      unless matched.empty?
 | 
				
			||||||
        raise Error, "Cannot determine ability conditions from block for #{action.inspect} #{subject.inspect}" if can_definition.block
 | 
					        if matched.any?{|can_definition| can_definition.conditions.nil? && can_definition.block }
 | 
				
			||||||
        can_definition.conditions || {}
 | 
					          raise Error, "Cannot determine ability conditions from block for #{action.inspect} #{subject.inspect}"
 | 
				
			||||||
 | 
					        end
 | 
				
			||||||
 | 
					        matched.map{|can_definition|
 | 
				
			||||||
 | 
					            [can_definition.base_behavior, can_definition.conditions]
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
      else
 | 
					      else
 | 
				
			||||||
        false
 | 
					        false
 | 
				
			||||||
      end
 | 
					      end
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
 | 
					    # Returns sql conditions for object, which responds to :sanitize_sql .
 | 
				
			||||||
 | 
					    # This is useful if you need to generate a database query based on the current ability.
 | 
				
			||||||
 | 
					    # 
 | 
				
			||||||
 | 
					    #   can :manage, User, :id => 1
 | 
				
			||||||
 | 
					    #   can :manage, User, :manager_id => 1
 | 
				
			||||||
 | 
					    #   cannot :manage, User, :self_managed => true
 | 
				
			||||||
 | 
					    #   sql_conditions :manage, User # returns not (self_managed = 't') AND ((manager_id = 1) OR (id = 1))
 | 
				
			||||||
 | 
					    #
 | 
				
			||||||
 | 
					    # Normally you will not call this method directly, but instead go through ActiveRecordAdditions#accessible_by method.
 | 
				
			||||||
 | 
					    # 
 | 
				
			||||||
 | 
					    # If the ability is not defined then false is returned so be sure to take that into consideration.
 | 
				
			||||||
 | 
					    # If there is just one :can ability, it conditions returned untouched.
 | 
				
			||||||
 | 
					    # If the ability is defined using a block then this will raise an exception since a hash of conditions cannot be
 | 
				
			||||||
 | 
					    # determined from that.   
 | 
				
			||||||
 | 
					    def sql_conditions(action, subject)
 | 
				
			||||||
 | 
					      conds = conditions(action, subject)
 | 
				
			||||||
 | 
					      return false if conds == false
 | 
				
			||||||
 | 
					      return (conds[0][1] || {}) if conds.size==1 && conds[0][0] == true # to match previous spec
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					      true_cond = subject.send(:sanitize_sql, ['?=?', true, true])
 | 
				
			||||||
 | 
					      false_cond = subject.send(:sanitize_sql, ['?=?', true, false])
 | 
				
			||||||
 | 
					      conds.reverse.inject(nil) do |sql, action|
 | 
				
			||||||
 | 
					        behavior, condition = action
 | 
				
			||||||
 | 
					        if condition
 | 
				
			||||||
 | 
					          condition = "#{subject.send(:sanitize_sql, condition)}"
 | 
				
			||||||
 | 
					          condition = "not (#{condition})" if behavior == false
 | 
				
			||||||
 | 
					        else
 | 
				
			||||||
 | 
					          condition = behavior ? true_cond : false_cond
 | 
				
			||||||
 | 
					        end
 | 
				
			||||||
 | 
					        case sql
 | 
				
			||||||
 | 
					          when nil then condition
 | 
				
			||||||
 | 
					          when true_cond
 | 
				
			||||||
 | 
					            behavior ? true_cond : condition
 | 
				
			||||||
 | 
					          when false_cond
 | 
				
			||||||
 | 
					            behavior ? condition : false_cond
 | 
				
			||||||
 | 
					          else
 | 
				
			||||||
 | 
					            behavior ? "(#{condition}) OR (#{sql})" : "#{condition} AND (#{sql})"
 | 
				
			||||||
 | 
					        end
 | 
				
			||||||
 | 
					      end
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
    # Returns the associations used in conditions. This is usually used in the :joins option for a search.
 | 
					    # Returns the associations used in conditions. This is usually used in the :joins option for a search.
 | 
				
			||||||
    # See ActiveRecordAdditions#accessible_by for use in Active Record.
 | 
					    # See ActiveRecordAdditions#accessible_by for use in Active Record.
 | 
				
			||||||
    def association_joins(action, subject)
 | 
					    def association_joins(action, subject)
 | 
				
			||||||
      can_definition = matching_can_definition(action, subject)
 | 
					      can_definitions = matching_can_definition(action, subject)
 | 
				
			||||||
      if can_definition
 | 
					      unless can_definitions.empty?
 | 
				
			||||||
        raise Error, "Cannot determine association joins from block for #{action.inspect} #{subject.inspect}" if can_definition.block
 | 
					        if can_definitions.any?{|can_definition| can_definition.conditions.nil? && can_definition.block }
 | 
				
			||||||
        can_definition.association_joins
 | 
					          raise Error, "Cannot determine association joins from block for #{action.inspect} #{subject.inspect}"
 | 
				
			||||||
 | 
					        end
 | 
				
			||||||
 | 
					        collect_association_joins(can_definitions)
 | 
				
			||||||
 | 
					      else
 | 
				
			||||||
 | 
					        nil
 | 
				
			||||||
      end
 | 
					      end
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
@ -217,9 +274,18 @@ module CanCan
 | 
				
			|||||||
    end
 | 
					    end
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    def matching_can_definition(action, subject)
 | 
					    def matching_can_definition(action, subject)
 | 
				
			||||||
      can_definitions.reverse.detect do |can_definition|
 | 
					      if block_given?
 | 
				
			||||||
 | 
					        can_definitions.reverse.each do |can_definition|
 | 
				
			||||||
          can_definition.expand_actions(aliased_actions)
 | 
					          can_definition.expand_actions(aliased_actions)
 | 
				
			||||||
        can_definition.matches? action, subject
 | 
					          if can_definition.matches? action, subject
 | 
				
			||||||
 | 
					            yield can_definition
 | 
				
			||||||
 | 
					            break if can_definition.conditions.nil? && can_definition.block.nil?
 | 
				
			||||||
 | 
					          end
 | 
				
			||||||
 | 
					        end
 | 
				
			||||||
 | 
					      else
 | 
				
			||||||
 | 
					        matched = []
 | 
				
			||||||
 | 
					        matching_can_definition(action, subject){|can_definition| matched << can_definition}
 | 
				
			||||||
 | 
					        matched
 | 
				
			||||||
      end
 | 
					      end
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
@ -230,5 +296,32 @@ module CanCan
 | 
				
			|||||||
        :update => [:edit],
 | 
					        :update => [:edit],
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    def collect_association_joins(can_definitions)
 | 
				
			||||||
 | 
					      joins = []
 | 
				
			||||||
 | 
					      can_definitions.each do |can_definition|
 | 
				
			||||||
 | 
					        merge_association_joins(joins, can_definition.association_joins || [])
 | 
				
			||||||
 | 
					      end
 | 
				
			||||||
 | 
					      clear_association_joins(joins)
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    def merge_association_joins(what, with)
 | 
				
			||||||
 | 
					      with.each do |join|
 | 
				
			||||||
 | 
					        name, nested = join.each_pair.first
 | 
				
			||||||
 | 
					        if at = what.detect{|h| h.has_key?(name) }
 | 
				
			||||||
 | 
					          at[name] = merge_association_joins(at[name], nested)
 | 
				
			||||||
 | 
					        else
 | 
				
			||||||
 | 
					          what << join
 | 
				
			||||||
 | 
					        end
 | 
				
			||||||
 | 
					      end
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    def clear_association_joins(joins)
 | 
				
			||||||
 | 
					      joins.map do |join| 
 | 
				
			||||||
 | 
					        name, nested = join.each_pair.first
 | 
				
			||||||
 | 
					        nested.empty? ? name : {name => clear_association_joins(nested)}
 | 
				
			||||||
 | 
					      end
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
				
			|||||||
@ -20,7 +20,7 @@ module CanCan
 | 
				
			|||||||
      # Here only the articles which the user can update are returned. This
 | 
					      # Here only the articles which the user can update are returned. This
 | 
				
			||||||
      # internally uses Ability#conditions method, see that for more information.
 | 
					      # internally uses Ability#conditions method, see that for more information.
 | 
				
			||||||
      def accessible_by(ability, action = :read)
 | 
					      def accessible_by(ability, action = :read)
 | 
				
			||||||
        conditions = ability.conditions(action, self) || {:id => nil}
 | 
					        conditions = ability.sql_conditions(action, self) || {:id => nil}
 | 
				
			||||||
        joins = ability.association_joins(action, self)
 | 
					        joins = ability.association_joins(action, self)
 | 
				
			||||||
        if respond_to? :where
 | 
					        if respond_to? :where
 | 
				
			||||||
          where(conditions).joins(joins)
 | 
					          where(conditions).joins(joins)
 | 
				
			||||||
 | 
				
			|||||||
@ -1,7 +1,7 @@
 | 
				
			|||||||
module CanCan
 | 
					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.
 | 
				
			||||||
  class CanDefinition # :nodoc:
 | 
					  class CanDefinition # :nodoc:
 | 
				
			||||||
    attr_reader :conditions, :block
 | 
					    attr_reader :conditions, :block, :base_behavior, :definitive
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    def initialize(base_behavior, action, subject, conditions, block)
 | 
					    def initialize(base_behavior, action, subject, conditions, block)
 | 
				
			||||||
      @base_behavior = base_behavior
 | 
					      @base_behavior = base_behavior
 | 
				
			||||||
@ -23,18 +23,19 @@ module CanCan
 | 
				
			|||||||
    
 | 
					    
 | 
				
			||||||
    def can?(action, subject, extra_args)
 | 
					    def can?(action, subject, extra_args)
 | 
				
			||||||
      result = can_without_base_behavior?(action, subject, extra_args)
 | 
					      result = can_without_base_behavior?(action, subject, extra_args)
 | 
				
			||||||
 | 
					      return :_NOT_MATCHED if result == :_NOT_MATCHED || !result
 | 
				
			||||||
      @base_behavior ? result : !result
 | 
					      @base_behavior ? result : !result
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def association_joins(conditions = @conditions)
 | 
					    def association_joins(conditions = @conditions)
 | 
				
			||||||
      joins = []
 | 
					      joins = []
 | 
				
			||||||
      conditions.each do |name, value|
 | 
					      (conditions || []).each do |name, value|
 | 
				
			||||||
        if value.kind_of? Hash
 | 
					        if value.kind_of? Hash
 | 
				
			||||||
          nested = association_joins(value)
 | 
					          nested = association_joins(value)
 | 
				
			||||||
          if nested
 | 
					          if nested
 | 
				
			||||||
            joins << {name => nested}
 | 
					            joins << {name => nested}
 | 
				
			||||||
          else
 | 
					          else
 | 
				
			||||||
            joins << name
 | 
					            joins << {name => []}
 | 
				
			||||||
          end
 | 
					          end
 | 
				
			||||||
        end
 | 
					        end
 | 
				
			||||||
      end
 | 
					      end
 | 
				
			||||||
@ -54,8 +55,10 @@ module CanCan
 | 
				
			|||||||
    def can_without_base_behavior?(action, subject, extra_args)
 | 
					    def can_without_base_behavior?(action, subject, extra_args)
 | 
				
			||||||
      if @block
 | 
					      if @block
 | 
				
			||||||
        call_block(action, subject, extra_args)
 | 
					        call_block(action, subject, extra_args)
 | 
				
			||||||
      elsif @conditions && subject.class != Class
 | 
					      elsif @conditions.kind_of?(Hash) && subject.class != Class
 | 
				
			||||||
        matches_conditions? subject
 | 
					        matches_conditions?(subject)
 | 
				
			||||||
 | 
					      elsif [true, false, :_NOT_MATCHES].include? @conditions
 | 
				
			||||||
 | 
					        @conditions
 | 
				
			||||||
      else
 | 
					      else
 | 
				
			||||||
        true
 | 
					        true
 | 
				
			||||||
      end
 | 
					      end
 | 
				
			||||||
 | 
				
			|||||||
@ -16,13 +16,27 @@ describe CanCan::Ability do
 | 
				
			|||||||
    @ability.can?(:foodfight, String).should be_false
 | 
					    @ability.can?(:foodfight, String).should be_false
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
  
 | 
					  
 | 
				
			||||||
  it "should return what block returns on a can call" do
 | 
					  it "should return what block returns on a can call, except for nil and false" do
 | 
				
			||||||
 | 
					    @ability.can :read, :all
 | 
				
			||||||
 | 
					    @ability.can :read, Symbol do |sym|
 | 
				
			||||||
 | 
					      [ sym ]
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					    @ability.can?(:read, Symbol).should == [ nil ]
 | 
				
			||||||
 | 
					    @ability.can?(:read, :some_symbol).should == [ :some_symbol ]
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  it "should pass to previous can definition, if block returns false or nil" do
 | 
				
			||||||
    @ability.can :read, :all
 | 
					    @ability.can :read, :all
 | 
				
			||||||
    @ability.can :read, Symbol do |sym|
 | 
					    @ability.can :read, Symbol do |sym|
 | 
				
			||||||
      sym
 | 
					      sym
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
    @ability.can?(:read, Symbol).should be_nil
 | 
					    @ability.can :read, Integer do |i|
 | 
				
			||||||
 | 
					      i > 0
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					    @ability.can?(:read, Symbol).should be_true
 | 
				
			||||||
    @ability.can?(:read, :some_symbol).should == :some_symbol
 | 
					    @ability.can?(:read, :some_symbol).should == :some_symbol
 | 
				
			||||||
 | 
					    @ability.can?(:read, 1).should be_true
 | 
				
			||||||
 | 
					    @ability.can?(:read, -1).should be_true
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
  
 | 
					  
 | 
				
			||||||
  it "should pass class with object if :all objects are accepted" do
 | 
					  it "should pass class with object if :all objects are accepted" do
 | 
				
			||||||
@ -121,6 +135,30 @@ 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
 | 
				
			||||||
 | 
					    #same as previous
 | 
				
			||||||
 | 
					    @ability.can :read, :all
 | 
				
			||||||
 | 
					    @ability.cannot :read, Integer do |int|
 | 
				
			||||||
 | 
					      int > 10 ? nil : ( int > 5 )
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					    @ability.can?(:read, "foo").should be_true
 | 
				
			||||||
 | 
					    @ability.can?(:read, 3).should be_true
 | 
				
			||||||
 | 
					    @ability.can?(:read, 8).should be_false
 | 
				
			||||||
 | 
					    @ability.can?(:read, 123).should be_true
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  it "should pass to previous cannot definition, if block returns false or nil" do
 | 
				
			||||||
 | 
					    @ability.cannot :read, :all
 | 
				
			||||||
 | 
					    @ability.can :read, Integer do |int|
 | 
				
			||||||
 | 
					      int > 10 ? nil : ( int > 5 )
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					    @ability.can?(:read, "foo").should be_false
 | 
				
			||||||
 | 
					    @ability.can?(:read, 3).should be_false
 | 
				
			||||||
 | 
					    @ability.can?(:read, 10).should be_true
 | 
				
			||||||
 | 
					    @ability.can?(:read, 123).should be_false
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  it "should append aliased actions" do
 | 
					  it "should append aliased actions" do
 | 
				
			||||||
    @ability.alias_action :update, :to => :modify
 | 
					    @ability.alias_action :update, :to => :modify
 | 
				
			||||||
    @ability.alias_action :destroy, :to => :modify
 | 
					    @ability.alias_action :destroy, :to => :modify
 | 
				
			||||||
@ -174,27 +212,48 @@ describe CanCan::Ability do
 | 
				
			|||||||
    @ability.can?(:read, [[4, 5, 6]]).should be_false
 | 
					    @ability.can?(:read, [[4, 5, 6]]).should be_false
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
  
 | 
					  
 | 
				
			||||||
  it "should return conditions for a given ability" do
 | 
					  it "should return array of behavior and conditions for a given ability" do
 | 
				
			||||||
    @ability.can :read, Array, :first => 1, :last => 3
 | 
					    @ability.can :read, Array, :first => 1, :last => 3
 | 
				
			||||||
    @ability.conditions(:show, Array).should == {:first => 1, :last => 3}
 | 
					    @ability.conditions(:show, Array).should == [[true, {:first => 1, :last => 3}]]
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
  
 | 
					  
 | 
				
			||||||
  it "should raise an exception when a block is used on condition" do
 | 
					  it "should raise an exception when a block is used on condition, and no" do
 | 
				
			||||||
    @ability.can :read, Array do |a|
 | 
					    @ability.can :read, Array do |a|
 | 
				
			||||||
      true
 | 
					      true
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
    lambda { @ability.conditions(:show, Array) }.should raise_error(CanCan::Error, "Cannot determine ability conditions from block for :show Array")
 | 
					    lambda { @ability.conditions(:show, Array) }.should raise_error(CanCan::Error, "Cannot determine ability conditions from block for :show Array")
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
  
 | 
					  
 | 
				
			||||||
  it "should return an empty hash for conditions when there are no conditions" do
 | 
					  it "should return an array with just behavior for conditions when there are no conditions" do
 | 
				
			||||||
    @ability.can :read, Array
 | 
					    @ability.can :read, Array
 | 
				
			||||||
    @ability.conditions(:show, Array).should == {}
 | 
					    @ability.conditions(:show, Array).should == [ [true, nil] ]
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
  
 | 
					  
 | 
				
			||||||
  it "should return false when performed on an action which isn't defined" do
 | 
					  it "should return false when performed on an action which isn't defined" do
 | 
				
			||||||
    @ability.conditions(:foo, Array).should == false
 | 
					    @ability.conditions(:foo, Array).should == false
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
  
 | 
					  
 | 
				
			||||||
 | 
					  it "should return appropriate sql conditions" do
 | 
				
			||||||
 | 
					    obj = Class.new do
 | 
				
			||||||
 | 
					      def self.sanitize_sql(hash_cond)
 | 
				
			||||||
 | 
					        case hash_cond
 | 
				
			||||||
 | 
					        when Hash then hash_cond.map{|name, value| "#{name}=#{value}"}
 | 
				
			||||||
 | 
					        when Array
 | 
				
			||||||
 | 
					          hash_cond.shift.gsub('?'){"#{hash_cond.shift.inspect}"}
 | 
				
			||||||
 | 
					        when String then hash_cond
 | 
				
			||||||
 | 
					        end
 | 
				
			||||||
 | 
					      end
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					    @ability.can :read, obj
 | 
				
			||||||
 | 
					    @ability.can :manage, obj, :id => 1
 | 
				
			||||||
 | 
					    @ability.can :update, obj, :manager_id => 1
 | 
				
			||||||
 | 
					    @ability.cannot :update, obj, :self_managed => true
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    @ability.sql_conditions(:update, obj).should == 'not (self_managed=true) AND ((manager_id=1) OR (id=1))'
 | 
				
			||||||
 | 
					    @ability.sql_conditions(:manage, obj).should == {:id=>1}
 | 
				
			||||||
 | 
					    @ability.sql_conditions(:read, obj).should == 'true=true'
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
  it "should has eated cheezburger" do
 | 
					  it "should has eated cheezburger" do
 | 
				
			||||||
    lambda {
 | 
					    lambda {
 | 
				
			||||||
      @ability.can? :has, :cheezburger
 | 
					      @ability.can? :has, :cheezburger
 | 
				
			||||||
 | 
				
			|||||||
@ -17,7 +17,7 @@ describe CanCan::CanDefinition do
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  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.association_joins.should == [:foo]
 | 
					    @can.association_joins.should == [{:foo=>[]}]
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  it "should return multiple associations for joins" do
 | 
					  it "should return multiple associations for joins" do
 | 
				
			||||||
@ -28,6 +28,6 @@ describe CanCan::CanDefinition do
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  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.association_joins.should == [{:foo => [:bar]}]
 | 
					    @can.association_joins.should == [{:foo => [{:bar=>[]}]}]
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user