turning load and authorize resource methods into class methods which set up the before filter so they can accept additional arguments

This commit is contained in:
Ryan Bates 2009-12-13 10:03:21 -08:00
parent 43947c893d
commit a5f98824a0
4 changed files with 70 additions and 52 deletions

View File

@ -1,3 +1,5 @@
* BACKWARDS INCOMPATIBLE: turning load and authorize resource methods into class methods which set up the before filter so they can accept additional arguments.
0.2.1 (Nov 26, 2009) 0.2.1 (Nov 26, 2009)
* many internal refactorings - see issues #11 and #12 * many internal refactorings - see issues #11 and #12

View File

@ -3,7 +3,56 @@ module CanCan
# This module is automatically included into all controllers. # This module is automatically included into all controllers.
# It also makes the "can?" and "cannot?" methods available to all views. # It also makes the "can?" and "cannot?" methods available to all views.
module ControllerAdditions module ControllerAdditions
module ClassMethods
# Sets up a before filter which loads and authorizes the current resource. This accepts the
# same arguments as load_resource and authorize_resource. See those methods for details.
#
# class BooksController < ApplicationController
# load_and_authorize_resource
# end
#
def load_and_authorize_resource(*args)
before_filter { |c| ResourceAuthorization.new(c, c.params, *args).load_and_authorize_resource }
end
# Sets up a before filter which loads the appropriate model resource into an instance variable.
# For example, given an ArticlesController it will load the current article into the @article
# instance variable. It does this by either calling Article.find(params[:id]) or
# Article.new(params[:article]) depending upon the action. It does nothing for the "index"
# action.
#
# You would call this method directly on the controller class.
#
# class BooksController < ApplicationController
# load_resource
# end
#
# See load_and_authorize_resource to automatically authorize the resource too.
def load_resource(*args) # TODO add documentation for options which can be passed.
before_filter { |c| ResourceAuthorization.new(c, c.params, *args).load_resource }
end
# Sets up a before filter which authorizes the current resource using the instance variable.
# For example, if you have an ArticlesController it will check the @article instance variable
# and ensure the user can perform the current action on it. Under the hood it is doing
# something like the following.
#
# unauthorized! if cannot?(params[:action].to_sym, @article || Article)
#
# You would call this method directly on the controller class.
#
# class BooksController < ApplicationController
# authorize_resource
# end
#
# See load_and_authorize_resource to automatically load the resource too.
def authorize_resource(*args)
before_filter { |c| ResourceAuthorization.new(c, c.params, *args).authorize_resource }
end
end
def self.included(base) def self.included(base)
base.extend ClassMethods
base.helper_method :can?, :cannot? base.helper_method :can?, :cannot?
end end
@ -70,48 +119,6 @@ module CanCan
def cannot?(*args) def cannot?(*args)
(@current_ability ||= current_ability).cannot?(*args) (@current_ability ||= current_ability).cannot?(*args)
end end
# This method loads the appropriate model resource into an instance variable. For example,
# given an ArticlesController it will load the current article into the @article instance
# variable. It does this by either calling Article.find(params[:id]) or
# Article.new(params[:article]) depending upon the action. It does nothing for the "index"
# action.
#
# You would often use this as a before filter in the controller. See
# load_and_authorize_resource to handle authorization too.
#
# before_filter :load_resource
#
def load_resource
ResourceAuthorization.new(self, params).load_resource
end
# Authorizes the resource in the current instance variable. For example,
# if you have an ArticlesController it will check the @article instance variable
# and ensure the user can perform the current action on it.
# Under the hood it is doing something like the following.
#
# unauthorized! if cannot?(params[:action].to_sym, @article || Article)
#
# You would often use this as a before filter in the controller.
#
# before_filter :authorize_resource
#
# See load_and_authorize_resource to automatically load the resource too.
def authorize_resource
ResourceAuthorization.new(self, params).authorize_resource
end
# Calls load_resource to load the current resource model into an instance variable.
# Then calls authorize_resource to ensure the current user is authorized to access the page.
# You would often use this as a before filter in the controller.
#
# before_filter :load_and_authorize_resource
#
def load_and_authorize_resource
load_resource
authorize_resource
end
end end
end end

View File

@ -27,19 +27,21 @@ describe CanCan::ControllerAdditions do
@controller.cannot?(:foo, :bar).should be_true @controller.cannot?(:foo, :bar).should be_true
end end
it "should load resource" do it "load_and_authorize_resource should setup a before filter which passes call to ResourceAuthorization" do
mock.instance_of(CanCan::ResourceAuthorization).load_resource stub(CanCan::ResourceAuthorization).new(@controller, @controller.params, :foo => :bar).mock!.load_and_authorize_resource
@controller.load_resource mock(@controller_class).before_filter { |block| block.call(@controller) }
@controller_class.load_and_authorize_resource :foo => :bar
end end
it "should authorize resource" do it "authorize_resource should setup a before filter which passes call to ResourceAuthorization" do
mock.instance_of(CanCan::ResourceAuthorization).authorize_resource stub(CanCan::ResourceAuthorization).new(@controller, @controller.params, :foo => :bar).mock!.authorize_resource
@controller.authorize_resource mock(@controller_class).before_filter { |block| block.call(@controller) }
@controller_class.authorize_resource :foo => :bar
end end
it "should load and authorize resource in one call through controller" do it "load_resource should setup a before filter which passes call to ResourceAuthorization" do
mock(@controller).load_resource stub(CanCan::ResourceAuthorization).new(@controller, @controller.params, :foo => :bar).mock!.load_resource
mock(@controller).authorize_resource mock(@controller_class).before_filter { |block| block.call(@controller) }
@controller.load_and_authorize_resource @controller_class.load_resource :foo => :bar
end end
end end

View File

@ -56,4 +56,11 @@ describe CanCan::ResourceAuthorization do
authorization.authorize_resource authorization.authorize_resource
}.should raise_error(CanCan::AccessDenied) }.should raise_error(CanCan::AccessDenied)
end end
it "should call load_resource and authorize_resource for load_and_authorize_resource" do
authorization = CanCan::ResourceAuthorization.new(@controller, :controller => "abilities", :action => "show")
mock(authorization).load_resource
mock(authorization).authorize_resource
authorization.load_and_authorize_resource
end
end end