adding 'cannot?' method which performs opposite check of 'can?' - closes #1

This commit is contained in:
Ryan Bates 2009-11-17 10:46:16 -08:00
parent df276536ab
commit 0f49b5478f
6 changed files with 27 additions and 8 deletions

View File

@ -1,3 +1,5 @@
* adding "cannot?" method to ability, controller, and view which is inverse of "can?" - see issue #1
* BACKWARDS INCOMPATIBLE: use Ability#initialize instead of 'prepare' to set up abilities - see issue #4 * BACKWARDS INCOMPATIBLE: use Ability#initialize instead of 'prepare' to set up abilities - see issue #4
*0.1.0* (Nov 16th, 2009) *0.1.0* (Nov 16th, 2009)

View File

@ -38,17 +38,17 @@ First define a class called Ability, place it in "models/ability.rb".
This class is where all permissions will go. See the "Defining Abilities" section below for more information. This class is where all permissions will go. See the "Defining Abilities" section below for more information.
In the view layer you can access the current permissions at any point using the "can?" method. See "Checking Abilities" section below. In the view layer you can access the current permissions at any point using the "can?" and "cannot?" methods. See "Checking Abilities" section below.
<% if can? :update, @article %> <% if can? :update, @article %>
<%= link_to "Edit", edit_article_path(@article) %> <%= link_to "Edit", edit_article_path(@article) %>
<% end %> <% end %>
You can also use this method in the controller layer along with the "unauthorized!" method to restrict access. You can also use these methods in the controller layer along with the "unauthorized!" method to restrict access.
def show def show
@article = Article.find(params[:id]) @article = Article.find(params[:id])
unauthorized! unless can? :read, @article unauthorized! if cannot? :read, @article
end end
Setting this for every action can be tedious, therefore a before filter is also provided for automatically applying this setting to a RESTful style resource controller. Setting this for every action can be tedious, therefore a before filter is also provided for automatically applying this setting to a RESTful style resource controller.
@ -135,6 +135,10 @@ You can also pass the class instead of an instance (if you don't have one handy)
<%= link_to "New Project", new_project_path %> <%= link_to "New Project", new_project_path %>
<% end %> <% end %>
The "cannot?" method is for convenience and performs the opposite check of "can?"
cannot? :destroy, @project
== Custom Actions == Custom Actions
@ -148,7 +152,7 @@ There is no limit to what actions you can use to determine abilities. For exampl
# projects_controller.rb # projects_controller.rb
def update def update
unauthorized! if params[:project][:upload_picture] && !can?(:upload_picture, @project) unauthorized! if params[:project][:upload_picture] && cannot?(:upload_picture, @project)
# ... # ...
end end
@ -199,7 +203,7 @@ def test "user can only destroy projects which he owns"
user = User.new user = User.new
ability = Ability.new(user) ability = Ability.new(user)
assert ability.can?(:destroy, Project.new(:user => user)) assert ability.can?(:destroy, Project.new(:user => user))
assert !ability.can?(:destroy, Project.new) assert ability.cannot?(:destroy, Project.new)
end end

View File

@ -21,6 +21,10 @@ module CanCan
false false
end end
def cannot?(*args)
!can?(*args)
end
def possible_actions_for(initial_action) def possible_actions_for(initial_action)
actions = [initial_action] actions = [initial_action]
(@aliased_actions || default_alias_actions).each do |target, aliases| (@aliased_actions || default_alias_actions).each do |target, aliases|

View File

@ -1,7 +1,7 @@
module CanCan module CanCan
module ControllerAdditions module ControllerAdditions
def self.included(base) def self.included(base)
base.helper_method :can? base.helper_method :can?, :cannot?
end end
def unauthorized! def unauthorized!
@ -16,6 +16,10 @@ module CanCan
(@current_ability ||= current_ability).can?(*args) (@current_ability ||= current_ability).can?(*args)
end end
def cannot?(*args)
(@current_ability ||= current_ability).cannot?(*args)
end
def load_resource # TODO this could use some refactoring def load_resource # TODO this could use some refactoring
unless params[:action] == "index" unless params[:action] == "index"
if params[:id] if params[:id]

View File

@ -81,4 +81,8 @@ describe CanCan::Ability do
it "should not respond to prepare (now using initialize)" do it "should not respond to prepare (now using initialize)" do
@ability.should_not respond_to(:prepare) @ability.should_not respond_to(:prepare)
end end
it "should offer cannot? method which is simply invert of can?" do
@ability.cannot?(:tie, String).should be_true
end
end end

View File

@ -11,7 +11,7 @@ describe CanCan::ControllerAdditions do
before(:each) do before(:each) do
@controller_class = Class.new @controller_class = Class.new
@controller = @controller_class.new @controller = @controller_class.new
mock(@controller_class).helper_method(:can?) mock(@controller_class).helper_method(:can?, :cannot?)
@controller_class.send(:include, CanCan::ControllerAdditions) @controller_class.send(:include, CanCan::ControllerAdditions)
end end
@ -26,10 +26,11 @@ describe CanCan::ControllerAdditions do
@controller.current_ability.should be_kind_of(Ability) @controller.current_ability.should be_kind_of(Ability)
end end
it "should provide a can? method which goes through the current ability" do it "should provide a can? and cannot? methods which go through the current ability" do
stub(@controller).current_user { :current_user } stub(@controller).current_user { :current_user }
@controller.current_ability.should be_kind_of(Ability) @controller.current_ability.should be_kind_of(Ability)
@controller.can?(:foo, :bar).should be_false @controller.can?(:foo, :bar).should be_false
@controller.cannot?(:foo, :bar).should be_true
end end
it "should load the resource if params[:id] is specified" do it "should load the resource if params[:id] is specified" do