From 63634b4f5dd727a4bde505f8f066bb23a326b633 Mon Sep 17 00:00:00 2001 From: Ryan Bates Date: Sun, 13 Dec 2009 10:42:10 -0800 Subject: [PATCH] Adding :collection and :new options to load_resource method so we can specify behavior of additional actions if needed. --- CHANGELOG.rdoc | 2 ++ lib/cancan/controller_additions.rb | 18 +++++++++++++++++- lib/cancan/resource_authorization.rb | 19 +++++++++++++++++-- spec/cancan/resource_authorization_spec.rb | 19 +++++++++++++++++++ 4 files changed, 55 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.rdoc b/CHANGELOG.rdoc index 30ad53b..bc82591 100644 --- a/CHANGELOG.rdoc +++ b/CHANGELOG.rdoc @@ -1,3 +1,5 @@ +* Adding :collection and :new options to load_resource method so we can specify behavior of additional actions if needed. + * 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) diff --git a/lib/cancan/controller_additions.rb b/lib/cancan/controller_additions.rb index 4a0d535..410c7a0 100644 --- a/lib/cancan/controller_additions.rb +++ b/lib/cancan/controller_additions.rb @@ -28,7 +28,23 @@ module CanCan # 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. + # + # Options: + # [:+collection+] + # Specify which actions are resource collection actions in addition to :+index+. This + # is usually not necessary because it will try to guess depending on if an :+id+ + # is present in +params+. + # + # load_resource :collection => [:sort, :list] + # + # [:+new+] + # Specify which actions are new resource actions in addition to :+new+ and :+create+. + # Pass an action name into here if you would like to build a new resource instead of + # fetch one. + # + # load_resource :new => :build + # + def load_resource(*args) before_filter { |c| ResourceAuthorization.new(c, c.params, *args).load_resource } end diff --git a/lib/cancan/resource_authorization.rb b/lib/cancan/resource_authorization.rb index 47a86c3..fad7a82 100644 --- a/lib/cancan/resource_authorization.rb +++ b/lib/cancan/resource_authorization.rb @@ -2,9 +2,10 @@ module CanCan class ResourceAuthorization # :nodoc: attr_reader :params - def initialize(controller, params) + def initialize(controller, params, options = {}) @controller = controller @params = params + @options = options end def load_and_authorize_resource @@ -13,7 +14,13 @@ module CanCan end def load_resource - self.model_instance = params[:id] ? model_class.find(params[:id]) : model_class.new(params[model_name.to_sym]) unless params[:action] == "index" + unless collection_actions.include? params[:action].to_sym + if new_actions.include? params[:action].to_sym + self.model_instance = model_class.new(params[model_name.to_sym]) + else + self.model_instance = model_class.find(params[:id]) if params[:id] + end + end end def authorize_resource @@ -37,5 +44,13 @@ module CanCan def model_instance=(instance) @controller.instance_variable_set("@#{model_name}", instance) end + + def collection_actions + [:index] + [@options[:collection]].flatten + end + + def new_actions + [:new, :create] + [@options[:new]].flatten + end end end diff --git a/spec/cancan/resource_authorization_spec.rb b/spec/cancan/resource_authorization_spec.rb index 23fa701..3148d81 100644 --- a/spec/cancan/resource_authorization_spec.rb +++ b/spec/cancan/resource_authorization_spec.rb @@ -63,4 +63,23 @@ describe CanCan::ResourceAuthorization do mock(authorization).authorize_resource authorization.load_and_authorize_resource end + + it "should not build a resource when on custom collection action" do + authorization = CanCan::ResourceAuthorization.new(@controller, {:controller => "abilities", :action => "sort"}, {:collection => [:sort, :list]}) + authorization.load_resource + @controller.instance_variable_get(:@ability).should be_nil + end + + it "should build a resource when on custom new action even when params[:id] exists" do + stub(Ability).new(nil) { :some_resource } + authorization = CanCan::ResourceAuthorization.new(@controller, {:controller => "abilities", :action => "build", :id => 123}, {:new => :build}) + authorization.load_resource + @controller.instance_variable_get(:@ability).should == :some_resource + end + + it "should not try to load resource for other action if params[:id] is undefined" do + authorization = CanCan::ResourceAuthorization.new(@controller, {:controller => "abilities", :action => "list"}) + authorization.load_resource + @controller.instance_variable_get(:@ability).should be_nil + end end