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…
Reference in New Issue
Block a user