default ActiveRecordAdditions#can method action to :read and use 'scoped' if 'where' is not available
This commit is contained in:
		
							parent
							
								
									3c68a911d0
								
							
						
					
					
						commit
						37f482e8d5
					
				
							
								
								
									
										21
									
								
								README.rdoc
									
									
									
									
									
								
							
							
						
						
									
										21
									
								
								README.rdoc
									
									
									
									
									
								
							@ -178,6 +178,21 @@ If you want to customize the loading behavior on certain actions, you can do so
 | 
				
			|||||||
Here the @book instance variable is already set so it will not be loaded again for that action. This works for nested resources as well.
 | 
					Here the @book instance variable is already set so it will not be loaded again for that action. This works for nested resources as well.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					== Fetching Records
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Sometimes you need to restrict which records are returned from the database based on what the user is able to access. This can be done with the +can+ method on any Active Record model. Simply pass it the current ability and an action.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @articles = Article.can(current_ability, :read)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The action defaults to :read so that can optionally be left out.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @articles = Article.can(current_ability)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Here only the records which the user can read will be returned. This is an Active Record scope so other scopes and pagination can be chained onto it.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Note: This does not work for abilities which were defined by a block because the conditions hash can not be determined from them. Instead an exception will be raised.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
== Assumptions & Configuring
 | 
					== Assumptions & Configuring
 | 
				
			||||||
 | 
					
 | 
				
			||||||
CanCan makes two assumptions about your application.
 | 
					CanCan makes two assumptions about your application.
 | 
				
			||||||
@ -205,6 +220,12 @@ It is very easy to test the Ability model since you can call "can?" directly on
 | 
				
			|||||||
    assert ability.cannot?(:destroy, Project.new)
 | 
					    assert ability.cannot?(:destroy, Project.new)
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					A matcher called +be_able_to+ is provided for testing abilities in RSpec.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  require "cancan/matchers"
 | 
				
			||||||
 | 
					  # ...
 | 
				
			||||||
 | 
					  ability.should be_able_to(:destroy, Project.new)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
== Special Thanks
 | 
					== Special Thanks
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -191,9 +191,7 @@ module CanCan
 | 
				
			|||||||
    #   can :read, Article, :visible => true
 | 
					    #   can :read, Article, :visible => true
 | 
				
			||||||
    #   conditions :read, Article # returns { :visible => true }
 | 
					    #   conditions :read, Article # returns { :visible => true }
 | 
				
			||||||
    # 
 | 
					    # 
 | 
				
			||||||
    # For example, you can use this in Active Record find conditions to only fetch articles the user has permission to read.
 | 
					    # Normally you will not call this method directly, but instead go through ActiveRecordAdditions#can method.
 | 
				
			||||||
    # 
 | 
					 | 
				
			||||||
    #   Article.where(current_ability.conditions(:read, Article))
 | 
					 | 
				
			||||||
    # 
 | 
					    # 
 | 
				
			||||||
    # If the ability is not defined then false is returned so be sure to take that into consideration.
 | 
					    # If the ability is not defined then false is returned so be sure to take that into consideration.
 | 
				
			||||||
    # 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
 | 
				
			||||||
 | 
				
			|||||||
@ -2,8 +2,30 @@ module CanCan
 | 
				
			|||||||
  # This module is automatically included into all Active Record.
 | 
					  # This module is automatically included into all Active Record.
 | 
				
			||||||
  module ActiveRecordAdditions
 | 
					  module ActiveRecordAdditions
 | 
				
			||||||
    module ClassMethods
 | 
					    module ClassMethods
 | 
				
			||||||
      def can(ability, action)
 | 
					      # Returns a scope which fetches only the records that the passed ability
 | 
				
			||||||
        where(ability.conditions(action, self) || {:id => nil})
 | 
					      # can perform a given action on. The action defaults to :read. This
 | 
				
			||||||
 | 
					      # is usually called from a controller and passed the +current_ability+.
 | 
				
			||||||
 | 
					      #
 | 
				
			||||||
 | 
					      #   @articles = Article.can(current_ability)
 | 
				
			||||||
 | 
					      # 
 | 
				
			||||||
 | 
					      # Here only the articles which the user is able to read will be returned.
 | 
				
			||||||
 | 
					      # If the user does not have permission to read any articles then an empty
 | 
				
			||||||
 | 
					      # result is returned. Since this is a scope it can be combined with any
 | 
				
			||||||
 | 
					      # other scopes or pagination.
 | 
				
			||||||
 | 
					      # 
 | 
				
			||||||
 | 
					      # An alternative action can optionally be passed as a second argument.
 | 
				
			||||||
 | 
					      # 
 | 
				
			||||||
 | 
					      #   @articles = Article.can(current_ability, :update)
 | 
				
			||||||
 | 
					      # 
 | 
				
			||||||
 | 
					      # Here only the articles which the user can update are returned. This
 | 
				
			||||||
 | 
					      # internally uses Ability#conditions method, see that for more information.
 | 
				
			||||||
 | 
					      def can(ability, action = :read)
 | 
				
			||||||
 | 
					        conditions = ability.conditions(action, self) || {:id => nil}
 | 
				
			||||||
 | 
					        if respond_to? :where
 | 
				
			||||||
 | 
					          where(conditions)
 | 
				
			||||||
 | 
					        else
 | 
				
			||||||
 | 
					          scoped(:conditions => conditions)
 | 
				
			||||||
 | 
					        end
 | 
				
			||||||
      end
 | 
					      end
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
 | 
				
			|||||||
@ -3,7 +3,7 @@ require "spec_helper"
 | 
				
			|||||||
describe CanCan::ActiveRecordAdditions do
 | 
					describe CanCan::ActiveRecordAdditions do
 | 
				
			||||||
  before(:each) do
 | 
					  before(:each) do
 | 
				
			||||||
    @model_class = Class.new
 | 
					    @model_class = Class.new
 | 
				
			||||||
    stub(@model_class).where { :where_stub }
 | 
					    stub(@model_class).scoped { :scoped_stub }
 | 
				
			||||||
    @model_class.send(:include, CanCan::ActiveRecordAdditions)
 | 
					    @model_class.send(:include, CanCan::ActiveRecordAdditions)
 | 
				
			||||||
    @ability = Object.new
 | 
					    @ability = Object.new
 | 
				
			||||||
    @ability.extend(CanCan::Ability)
 | 
					    @ability.extend(CanCan::Ability)
 | 
				
			||||||
@ -19,4 +19,10 @@ describe CanCan::ActiveRecordAdditions do
 | 
				
			|||||||
    stub(@model_class).where(:foo => 1) { :found_records }
 | 
					    stub(@model_class).where(:foo => 1) { :found_records }
 | 
				
			||||||
    @model_class.can(@ability, :read).should == :found_records
 | 
					    @model_class.can(@ability, :read).should == :found_records
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  it "should default to :read ability and use scoped when where isn't available" do
 | 
				
			||||||
 | 
					    @ability.can :read, @model_class, :foo => 1
 | 
				
			||||||
 | 
					    stub(@model_class).scoped(:conditions => {:foo => 1}) { :found_records }
 | 
				
			||||||
 | 
					    @model_class.can(@ability).should == :found_records
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user