codeprimate-cancan 1.6.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. data/CHANGELOG.rdoc +291 -0
  2. data/Gemfile +20 -0
  3. data/LICENSE +20 -0
  4. data/README.rdoc +111 -0
  5. data/Rakefile +18 -0
  6. data/init.rb +1 -0
  7. data/lib/cancan.rb +13 -0
  8. data/lib/cancan/ability.rb +298 -0
  9. data/lib/cancan/controller_additions.rb +389 -0
  10. data/lib/cancan/controller_resource.rb +222 -0
  11. data/lib/cancan/exceptions.rb +50 -0
  12. data/lib/cancan/inherited_resource.rb +19 -0
  13. data/lib/cancan/matchers.rb +14 -0
  14. data/lib/cancan/model_adapters/abstract_adapter.rb +56 -0
  15. data/lib/cancan/model_adapters/active_record_adapter.rb +165 -0
  16. data/lib/cancan/model_adapters/data_mapper_adapter.rb +34 -0
  17. data/lib/cancan/model_adapters/default_adapter.rb +7 -0
  18. data/lib/cancan/model_adapters/mongoid_adapter.rb +53 -0
  19. data/lib/cancan/model_additions.rb +31 -0
  20. data/lib/cancan/rule.rb +142 -0
  21. data/lib/generators/cancan/ability/USAGE +4 -0
  22. data/lib/generators/cancan/ability/ability_generator.rb +11 -0
  23. data/lib/generators/cancan/ability/templates/ability.rb +28 -0
  24. data/spec/README.rdoc +28 -0
  25. data/spec/cancan/ability_spec.rb +419 -0
  26. data/spec/cancan/controller_additions_spec.rb +137 -0
  27. data/spec/cancan/controller_resource_spec.rb +412 -0
  28. data/spec/cancan/exceptions_spec.rb +58 -0
  29. data/spec/cancan/inherited_resource_spec.rb +42 -0
  30. data/spec/cancan/matchers_spec.rb +33 -0
  31. data/spec/cancan/model_adapters/active_record_adapter_spec.rb +278 -0
  32. data/spec/cancan/model_adapters/data_mapper_adapter_spec.rb +119 -0
  33. data/spec/cancan/model_adapters/default_adapter_spec.rb +7 -0
  34. data/spec/cancan/model_adapters/mongoid_adapter_spec.rb +216 -0
  35. data/spec/cancan/rule_spec.rb +39 -0
  36. data/spec/matchers.rb +13 -0
  37. data/spec/spec.opts +2 -0
  38. data/spec/spec_helper.rb +41 -0
  39. metadata +167 -0
@@ -0,0 +1,137 @@
1
+ require "spec_helper"
2
+
3
+ describe CanCan::ControllerAdditions do
4
+ before(:each) do
5
+ @controller_class = Class.new
6
+ @controller = @controller_class.new
7
+ stub(@controller).params { {} }
8
+ stub(@controller).current_user { :current_user }
9
+ mock(@controller_class).helper_method(:can?, :cannot?, :current_ability)
10
+ @controller_class.send(:include, CanCan::ControllerAdditions)
11
+ end
12
+
13
+ it "should raise ImplementationRemoved when attempting to call 'unauthorized!' on a controller" do
14
+ lambda { @controller.unauthorized! }.should raise_error(CanCan::ImplementationRemoved)
15
+ end
16
+
17
+ it "authorize! should assign @_authorized instance variable and pass args to current ability" do
18
+ mock(@controller.current_ability).authorize!(:foo, :bar)
19
+ @controller.authorize!(:foo, :bar)
20
+ @controller.instance_variable_get(:@_authorized).should be_true
21
+ end
22
+
23
+ it "should have a current_ability method which generates an ability for the current user" do
24
+ @controller.current_ability.should be_kind_of(Ability)
25
+ end
26
+
27
+ it "should provide a can? and cannot? methods which go through the current ability" do
28
+ @controller.current_ability.should be_kind_of(Ability)
29
+ @controller.can?(:foo, :bar).should be_false
30
+ @controller.cannot?(:foo, :bar).should be_true
31
+ end
32
+
33
+ it "load_and_authorize_resource should setup a before filter which passes call to ControllerResource" do
34
+ stub(CanCan::ControllerResource).new(@controller, nil, :foo => :bar).mock!.load_and_authorize_resource
35
+ mock(@controller_class).before_filter({}) { |options, block| block.call(@controller) }
36
+ @controller_class.load_and_authorize_resource :foo => :bar
37
+ end
38
+
39
+ it "load_and_authorize_resource should properly pass first argument as the resource name" do
40
+ stub(CanCan::ControllerResource).new(@controller, :project, :foo => :bar).mock!.load_and_authorize_resource
41
+ mock(@controller_class).before_filter({}) { |options, block| block.call(@controller) }
42
+ @controller_class.load_and_authorize_resource :project, :foo => :bar
43
+ end
44
+
45
+ it "load_and_authorize_resource with :prepend should prepend the before filter" do
46
+ mock(@controller_class).prepend_before_filter({})
47
+ @controller_class.load_and_authorize_resource :foo => :bar, :prepend => true
48
+ end
49
+
50
+ it "authorize_resource should setup a before filter which passes call to ControllerResource" do
51
+ stub(CanCan::ControllerResource).new(@controller, nil, :foo => :bar).mock!.authorize_resource
52
+ mock(@controller_class).before_filter(:except => :show) { |options, block| block.call(@controller) }
53
+ @controller_class.authorize_resource :foo => :bar, :except => :show
54
+ end
55
+
56
+ it "load_resource should setup a before filter which passes call to ControllerResource" do
57
+ stub(CanCan::ControllerResource).new(@controller, nil, :foo => :bar).mock!.load_resource
58
+ mock(@controller_class).before_filter(:only => [:show, :index]) { |options, block| block.call(@controller) }
59
+ @controller_class.load_resource :foo => :bar, :only => [:show, :index]
60
+ end
61
+
62
+ it "skip_authorization_check should set up a before filter which sets @_authorized to true" do
63
+ mock(@controller_class).before_filter(:filter_options) { |options, block| block.call(@controller) }
64
+ @controller_class.skip_authorization_check(:filter_options)
65
+ @controller.instance_variable_get(:@_authorized).should be_true
66
+ end
67
+
68
+ it "check_authorization should trigger AuthorizationNotPerformed in after filter" do
69
+ mock(@controller_class).after_filter(:only => [:test]) { |options, block| block.call(@controller) }
70
+ lambda {
71
+ @controller_class.check_authorization(:only => [:test])
72
+ }.should raise_error(CanCan::AuthorizationNotPerformed)
73
+ end
74
+
75
+ it "check_authorization should not trigger AuthorizationNotPerformed when :if is false" do
76
+ stub(@controller).check_auth? { false }
77
+ mock(@controller_class).after_filter({}) { |options, block| block.call(@controller) }
78
+ lambda {
79
+ @controller_class.check_authorization(:if => :check_auth?)
80
+ }.should_not raise_error(CanCan::AuthorizationNotPerformed)
81
+ end
82
+
83
+ it "check_authorization should not trigger AuthorizationNotPerformed when :unless is true" do
84
+ stub(@controller).engine_controller? { true }
85
+ mock(@controller_class).after_filter({}) { |options, block| block.call(@controller) }
86
+ lambda {
87
+ @controller_class.check_authorization(:unless => :engine_controller?)
88
+ }.should_not raise_error(CanCan::AuthorizationNotPerformed)
89
+ end
90
+
91
+ it "check_authorization should not raise error when @_authorized is set" do
92
+ @controller.instance_variable_set(:@_authorized, true)
93
+ mock(@controller_class).after_filter(:only => [:test]) { |options, block| block.call(@controller) }
94
+ lambda {
95
+ @controller_class.check_authorization(:only => [:test])
96
+ }.should_not raise_error(CanCan::AuthorizationNotPerformed)
97
+ end
98
+
99
+ it "cancan_resource_class should be ControllerResource by default" do
100
+ @controller.class.cancan_resource_class.should == CanCan::ControllerResource
101
+ end
102
+
103
+ it "cancan_resource_class should be InheritedResource when class includes InheritedResources::Actions" do
104
+ stub(@controller.class).ancestors { ["InheritedResources::Actions"] }
105
+ @controller.class.cancan_resource_class.should == CanCan::InheritedResource
106
+ end
107
+
108
+ it "cancan_skipper should be an empty hash with :authorize and :load options and remember changes" do
109
+ @controller_class.cancan_skipper.should == {:authorize => {}, :load => {}}
110
+ @controller_class.cancan_skipper[:load] = true
111
+ @controller_class.cancan_skipper[:load].should == true
112
+ end
113
+
114
+ it "skip_authorize_resource should add itself to the cancan skipper with given model name and options" do
115
+ @controller_class.skip_authorize_resource(:project, :only => [:index, :show])
116
+ @controller_class.cancan_skipper[:authorize][:project].should == {:only => [:index, :show]}
117
+ @controller_class.skip_authorize_resource(:only => [:index, :show])
118
+ @controller_class.cancan_skipper[:authorize][nil].should == {:only => [:index, :show]}
119
+ @controller_class.skip_authorize_resource(:article)
120
+ @controller_class.cancan_skipper[:authorize][:article].should == {}
121
+ end
122
+
123
+ it "skip_load_resource should add itself to the cancan skipper with given model name and options" do
124
+ @controller_class.skip_load_resource(:project, :only => [:index, :show])
125
+ @controller_class.cancan_skipper[:load][:project].should == {:only => [:index, :show]}
126
+ @controller_class.skip_load_resource(:only => [:index, :show])
127
+ @controller_class.cancan_skipper[:load][nil].should == {:only => [:index, :show]}
128
+ @controller_class.skip_load_resource(:article)
129
+ @controller_class.cancan_skipper[:load][:article].should == {}
130
+ end
131
+
132
+ it "skip_load_and_authore_resource should add itself to the cancan skipper with given model name and options" do
133
+ @controller_class.skip_load_and_authorize_resource(:project, :only => [:index, :show])
134
+ @controller_class.cancan_skipper[:load][:project].should == {:only => [:index, :show]}
135
+ @controller_class.cancan_skipper[:authorize][:project].should == {:only => [:index, :show]}
136
+ end
137
+ end
@@ -0,0 +1,412 @@
1
+ require "spec_helper"
2
+
3
+ describe CanCan::ControllerResource do
4
+ before(:each) do
5
+ @params = HashWithIndifferentAccess.new(:controller => "projects")
6
+ @controller_class = Class.new
7
+ @controller = @controller_class.new
8
+ @ability = Ability.new(nil)
9
+ stub(@controller).params { @params }
10
+ stub(@controller).current_ability { @ability }
11
+ stub(@controller_class).cancan_skipper { {:authorize => {}, :load => {}} }
12
+ end
13
+
14
+ it "should load the resource into an instance variable if params[:id] is specified" do
15
+ project = Project.create!
16
+ @params.merge!(:action => "show", :id => project.id)
17
+ resource = CanCan::ControllerResource.new(@controller)
18
+ resource.load_resource
19
+ @controller.instance_variable_get(:@project).should == project
20
+ end
21
+
22
+ it "should not load resource into an instance variable if already set" do
23
+ @params.merge!(:action => "show", :id => 123)
24
+ @controller.instance_variable_set(:@project, :some_project)
25
+ resource = CanCan::ControllerResource.new(@controller)
26
+ resource.load_resource
27
+ @controller.instance_variable_get(:@project).should == :some_project
28
+ end
29
+
30
+ it "should properly load resource for namespaced controller" do
31
+ project = Project.create!
32
+ @params.merge!(:controller => "admin/projects", :action => "show", :id => project.id)
33
+ resource = CanCan::ControllerResource.new(@controller)
34
+ resource.load_resource
35
+ @controller.instance_variable_get(:@project).should == project
36
+ end
37
+
38
+ it "should properly load resource for namespaced controller when using '::' for namespace" do
39
+ project = Project.create!
40
+ @params.merge!(:controller => "Admin::ProjectsController", :action => "show", :id => project.id)
41
+ resource = CanCan::ControllerResource.new(@controller)
42
+ resource.load_resource
43
+ @controller.instance_variable_get(:@project).should == project
44
+ end
45
+
46
+ it "should build a new resource with hash if params[:id] is not specified" do
47
+ @params.merge!(:action => "create", :project => {:name => "foobar"})
48
+ resource = CanCan::ControllerResource.new(@controller)
49
+ resource.load_resource
50
+ @controller.instance_variable_get(:@project).name.should == "foobar"
51
+ end
52
+
53
+ it "should build a new resource with attributes from current ability" do
54
+ @params.merge!(:action => "new")
55
+ @ability.can(:create, Project, :name => "from conditions")
56
+ resource = CanCan::ControllerResource.new(@controller)
57
+ resource.load_resource
58
+ @controller.instance_variable_get(:@project).name.should == "from conditions"
59
+ end
60
+
61
+ it "should override initial attributes with params" do
62
+ @params.merge!(:action => "new", :project => {:name => "from params"})
63
+ @ability.can(:create, Project, :name => "from conditions")
64
+ resource = CanCan::ControllerResource.new(@controller)
65
+ resource.load_resource
66
+ @controller.instance_variable_get(:@project).name.should == "from params"
67
+ end
68
+
69
+ it "should build a collection when on index action when class responds to accessible_by" do
70
+ stub(Project).accessible_by(@ability, :index) { :found_projects }
71
+ @params[:action] = "index"
72
+ resource = CanCan::ControllerResource.new(@controller, :project)
73
+ resource.load_resource
74
+ @controller.instance_variable_get(:@project).should be_nil
75
+ @controller.instance_variable_get(:@projects).should == :found_projects
76
+ end
77
+
78
+ it "should not build a collection when on index action when class does not respond to accessible_by" do
79
+ @params[:action] = "index"
80
+ resource = CanCan::ControllerResource.new(@controller)
81
+ resource.load_resource
82
+ @controller.instance_variable_get(:@project).should be_nil
83
+ @controller.instance_variable_defined?(:@projects).should be_false
84
+ end
85
+
86
+ it "should not use accessible_by when defining abilities through a block" do
87
+ stub(Project).accessible_by(@ability) { :found_projects }
88
+ @params[:action] = "index"
89
+ @ability.can(:read, Project) { |p| false }
90
+ resource = CanCan::ControllerResource.new(@controller)
91
+ resource.load_resource
92
+ @controller.instance_variable_get(:@project).should be_nil
93
+ @controller.instance_variable_defined?(:@projects).should be_false
94
+ end
95
+
96
+ it "should not authorize single resource in collection action" do
97
+ @params[:action] = "index"
98
+ @controller.instance_variable_set(:@project, :some_project)
99
+ stub(@controller).authorize!(:index, Project) { raise CanCan::AccessDenied }
100
+ resource = CanCan::ControllerResource.new(@controller)
101
+ lambda { resource.authorize_resource }.should raise_error(CanCan::AccessDenied)
102
+ end
103
+
104
+ it "should authorize parent resource in collection action" do
105
+ @params[:action] = "index"
106
+ @controller.instance_variable_set(:@category, :some_category)
107
+ stub(@controller).authorize!(:show, :some_category) { raise CanCan::AccessDenied }
108
+ resource = CanCan::ControllerResource.new(@controller, :category, :parent => true)
109
+ lambda { resource.authorize_resource }.should raise_error(CanCan::AccessDenied)
110
+ end
111
+
112
+ it "should perform authorization using controller action and loaded model" do
113
+ @params.merge!(:action => "show", :id => 123)
114
+ @controller.instance_variable_set(:@project, :some_project)
115
+ stub(@controller).authorize!(:show, :some_project) { raise CanCan::AccessDenied }
116
+ resource = CanCan::ControllerResource.new(@controller)
117
+ lambda { resource.authorize_resource }.should raise_error(CanCan::AccessDenied)
118
+ end
119
+
120
+ it "should perform authorization using controller action and non loaded model" do
121
+ @params.merge!(:action => "show", :id => 123)
122
+ stub(@controller).authorize!(:show, Project) { raise CanCan::AccessDenied }
123
+ resource = CanCan::ControllerResource.new(@controller)
124
+ lambda { resource.authorize_resource }.should raise_error(CanCan::AccessDenied)
125
+ end
126
+
127
+ it "should call load_resource and authorize_resource for load_and_authorize_resource" do
128
+ @params.merge!(:action => "show", :id => 123)
129
+ resource = CanCan::ControllerResource.new(@controller)
130
+ mock(resource).load_resource
131
+ mock(resource).authorize_resource
132
+ resource.load_and_authorize_resource
133
+ end
134
+
135
+ it "should not build a single resource when on custom collection action even with id" do
136
+ @params.merge!(:action => "sort", :id => 123)
137
+ resource = CanCan::ControllerResource.new(@controller, :collection => [:sort, :list])
138
+ resource.load_resource
139
+ @controller.instance_variable_get(:@project).should be_nil
140
+ end
141
+
142
+ it "should load a collection resource when on custom action with no id param" do
143
+ stub(Project).accessible_by(@ability, :sort) { :found_projects }
144
+ @params[:action] = "sort"
145
+ resource = CanCan::ControllerResource.new(@controller)
146
+ resource.load_resource
147
+ @controller.instance_variable_get(:@project).should be_nil
148
+ @controller.instance_variable_get(:@projects).should == :found_projects
149
+ end
150
+
151
+ it "should build a resource when on custom new action even when params[:id] exists" do
152
+ @params.merge!(:action => "build", :id => 123)
153
+ stub(Project).new { :some_project }
154
+ resource = CanCan::ControllerResource.new(@controller, :new => :build)
155
+ resource.load_resource
156
+ @controller.instance_variable_get(:@project).should == :some_project
157
+ end
158
+
159
+ it "should not try to load resource for other action if params[:id] is undefined" do
160
+ @params[:action] = "list"
161
+ resource = CanCan::ControllerResource.new(@controller)
162
+ resource.load_resource
163
+ @controller.instance_variable_get(:@project).should be_nil
164
+ end
165
+
166
+ it "should be a parent resource when name is provided which doesn't match controller" do
167
+ resource = CanCan::ControllerResource.new(@controller, :category)
168
+ resource.should be_parent
169
+ end
170
+
171
+ it "should not be a parent resource when name is provided which matches controller" do
172
+ resource = CanCan::ControllerResource.new(@controller, :project)
173
+ resource.should_not be_parent
174
+ end
175
+
176
+ it "should be parent if specified in options" do
177
+ resource = CanCan::ControllerResource.new(@controller, :project, {:parent => true})
178
+ resource.should be_parent
179
+ end
180
+
181
+ it "should not be parent if specified in options" do
182
+ resource = CanCan::ControllerResource.new(@controller, :category, {:parent => false})
183
+ resource.should_not be_parent
184
+ end
185
+
186
+ it "should load parent resource through proper id parameter" do
187
+ project = Project.create!
188
+ @params.merge!(:action => "index", :project_id => project.id)
189
+ resource = CanCan::ControllerResource.new(@controller, :project, :parent => true)
190
+ resource.load_resource
191
+ @controller.instance_variable_get(:@project).should == project
192
+ end
193
+
194
+ it "should load resource through the association of another parent resource using instance variable" do
195
+ @params.merge!(:action => "show", :id => 123)
196
+ category = Object.new
197
+ @controller.instance_variable_set(:@category, category)
198
+ stub(category).projects.stub!.find(123) { :some_project }
199
+ resource = CanCan::ControllerResource.new(@controller, :through => :category)
200
+ resource.load_resource
201
+ @controller.instance_variable_get(:@project).should == :some_project
202
+ end
203
+
204
+ it "should load resource through the custom association name" do
205
+ @params.merge!(:action => "show", :id => 123)
206
+ category = Object.new
207
+ @controller.instance_variable_set(:@category, category)
208
+ stub(category).custom_projects.stub!.find(123) { :some_project }
209
+ resource = CanCan::ControllerResource.new(@controller, :through => :category, :through_association => :custom_projects)
210
+ resource.load_resource
211
+ @controller.instance_variable_get(:@project).should == :some_project
212
+ end
213
+
214
+ it "should load resource through the association of another parent resource using method" do
215
+ @params.merge!(:action => "show", :id => 123)
216
+ category = Object.new
217
+ stub(@controller).category { category }
218
+ stub(category).projects.stub!.find(123) { :some_project }
219
+ resource = CanCan::ControllerResource.new(@controller, :through => :category)
220
+ resource.load_resource
221
+ @controller.instance_variable_get(:@project).should == :some_project
222
+ end
223
+
224
+ it "should not load through parent resource if instance isn't loaded when shallow" do
225
+ project = Project.create!
226
+ @params.merge!(:action => "show", :id => project.id)
227
+ resource = CanCan::ControllerResource.new(@controller, :through => :category, :shallow => true)
228
+ resource.load_resource
229
+ @controller.instance_variable_get(:@project).should == project
230
+ end
231
+
232
+ it "should raise AccessDenied when attempting to load resource through nil" do
233
+ project = Project.create!
234
+ @params.merge!(:action => "show", :id => project.id)
235
+ resource = CanCan::ControllerResource.new(@controller, :through => :category)
236
+ lambda {
237
+ resource.load_resource
238
+ }.should raise_error(CanCan::AccessDenied) { |exception|
239
+ exception.action.should == :show
240
+ exception.subject.should == Project
241
+ }
242
+ @controller.instance_variable_get(:@project).should be_nil
243
+ end
244
+
245
+ it "should authorize nested resource through parent association on index action" do
246
+ @params.merge!(:action => "index")
247
+ category = Object.new
248
+ @controller.instance_variable_set(:@category, category)
249
+ stub(@controller).authorize!(:index, category => Project) { raise CanCan::AccessDenied }
250
+ resource = CanCan::ControllerResource.new(@controller, :through => :category)
251
+ lambda { resource.authorize_resource }.should raise_error(CanCan::AccessDenied)
252
+ end
253
+
254
+ it "should load through first matching if multiple are given" do
255
+ @params.merge!(:action => "show", :id => 123)
256
+ category = Object.new
257
+ @controller.instance_variable_set(:@category, category)
258
+ stub(category).projects.stub!.find(123) { :some_project }
259
+ resource = CanCan::ControllerResource.new(@controller, :through => [:category, :user])
260
+ resource.load_resource
261
+ @controller.instance_variable_get(:@project).should == :some_project
262
+ end
263
+
264
+ it "should find record through has_one association with :singleton option without id param" do
265
+ @params.merge!(:action => "show", :id => nil)
266
+ category = Object.new
267
+ @controller.instance_variable_set(:@category, category)
268
+ stub(category).project { :some_project }
269
+ resource = CanCan::ControllerResource.new(@controller, :through => :category, :singleton => true)
270
+ resource.load_resource
271
+ @controller.instance_variable_get(:@project).should == :some_project
272
+ end
273
+
274
+ it "should not build record through has_one association with :singleton option because it can cause it to delete it in the database" do
275
+ @params.merge!(:action => "create", :project => {:name => "foobar"})
276
+ category = Category.new
277
+ @controller.instance_variable_set(:@category, category)
278
+ resource = CanCan::ControllerResource.new(@controller, :through => :category, :singleton => true)
279
+ resource.load_resource
280
+ @controller.instance_variable_get(:@project).name.should == "foobar"
281
+ @controller.instance_variable_get(:@project).category.should == category
282
+ end
283
+
284
+ it "should find record through has_one association with :singleton and :shallow options" do
285
+ project = Project.create!
286
+ @params.merge!(:action => "show", :id => project.id)
287
+ resource = CanCan::ControllerResource.new(@controller, :through => :category, :singleton => true, :shallow => true)
288
+ resource.load_resource
289
+ @controller.instance_variable_get(:@project).should == project
290
+ end
291
+
292
+ it "should build record through has_one association with :singleton and :shallow options" do
293
+ @params.merge!(:action => "create", :project => {:name => "foobar"})
294
+ resource = CanCan::ControllerResource.new(@controller, :through => :category, :singleton => true, :shallow => true)
295
+ resource.load_resource
296
+ @controller.instance_variable_get(:@project).name.should == "foobar"
297
+ end
298
+
299
+ it "should only authorize :show action on parent resource" do
300
+ project = Project.create!
301
+ @params.merge!(:action => "new", :project_id => project.id)
302
+ stub(@controller).authorize!(:show, project) { raise CanCan::AccessDenied }
303
+ resource = CanCan::ControllerResource.new(@controller, :project, :parent => true)
304
+ lambda { resource.load_and_authorize_resource }.should raise_error(CanCan::AccessDenied)
305
+ end
306
+
307
+ it "should load the model using a custom class" do
308
+ project = Project.create!
309
+ @params.merge!(:action => "show", :id => project.id)
310
+ resource = CanCan::ControllerResource.new(@controller, :class => Project)
311
+ resource.load_resource
312
+ @controller.instance_variable_get(:@project).should == project
313
+ end
314
+
315
+ it "should authorize based on resource name if class is false" do
316
+ @params.merge!(:action => "show", :id => 123)
317
+ stub(@controller).authorize!(:show, :project) { raise CanCan::AccessDenied }
318
+ resource = CanCan::ControllerResource.new(@controller, :class => false)
319
+ lambda { resource.authorize_resource }.should raise_error(CanCan::AccessDenied)
320
+ end
321
+
322
+ it "should load and authorize using custom instance name" do
323
+ project = Project.create!
324
+ @params.merge!(:action => "show", :id => project.id)
325
+ stub(@controller).authorize!(:show, project) { raise CanCan::AccessDenied }
326
+ resource = CanCan::ControllerResource.new(@controller, :instance_name => :custom_project)
327
+ lambda { resource.load_and_authorize_resource }.should raise_error(CanCan::AccessDenied)
328
+ @controller.instance_variable_get(:@custom_project).should == project
329
+ end
330
+
331
+ it "should load resource using custom find_by attribute" do
332
+ project = Project.create!(:name => "foo")
333
+ @params.merge!(:action => "show", :id => "foo")
334
+ resource = CanCan::ControllerResource.new(@controller, :find_by => :name)
335
+ resource.load_resource
336
+ @controller.instance_variable_get(:@project).should == project
337
+ end
338
+
339
+ it "should allow full find method to be passed into find_by option" do
340
+ project = Project.create!(:name => "foo")
341
+ @params.merge!(:action => "show", :id => "foo")
342
+ resource = CanCan::ControllerResource.new(@controller, :find_by => :find_by_name)
343
+ resource.load_resource
344
+ @controller.instance_variable_get(:@project).should == project
345
+ end
346
+
347
+ it "should raise ImplementationRemoved when adding :name option" do
348
+ lambda {
349
+ CanCan::ControllerResource.new(@controller, :name => :foo)
350
+ }.should raise_error(CanCan::ImplementationRemoved)
351
+ end
352
+
353
+ it "should raise ImplementationRemoved exception when specifying :resource option since it is no longer used" do
354
+ lambda {
355
+ CanCan::ControllerResource.new(@controller, :resource => Project)
356
+ }.should raise_error(CanCan::ImplementationRemoved)
357
+ end
358
+
359
+ it "should raise ImplementationRemoved exception when passing :nested option" do
360
+ lambda {
361
+ CanCan::ControllerResource.new(@controller, :nested => :project)
362
+ }.should raise_error(CanCan::ImplementationRemoved)
363
+ end
364
+
365
+ it "should skip resource behavior for :only actions in array" do
366
+ stub(@controller_class).cancan_skipper { {:load => {nil => {:only => [:index, :show]}}} }
367
+ @params.merge!(:action => "index")
368
+ CanCan::ControllerResource.new(@controller).skip?(:load).should be_true
369
+ CanCan::ControllerResource.new(@controller, :some_resource).skip?(:load).should be_false
370
+ @params.merge!(:action => "show")
371
+ CanCan::ControllerResource.new(@controller).skip?(:load).should be_true
372
+ @params.merge!(:action => "other_action")
373
+ CanCan::ControllerResource.new(@controller).skip?(:load).should be_false
374
+ end
375
+
376
+ it "should skip resource behavior for :only one action on resource" do
377
+ stub(@controller_class).cancan_skipper { {:authorize => {:project => {:only => :index}}} }
378
+ @params.merge!(:action => "index")
379
+ CanCan::ControllerResource.new(@controller).skip?(:authorize).should be_false
380
+ CanCan::ControllerResource.new(@controller, :project).skip?(:authorize).should be_true
381
+ @params.merge!(:action => "other_action")
382
+ CanCan::ControllerResource.new(@controller, :project).skip?(:authorize).should be_false
383
+ end
384
+
385
+ it "should skip resource behavior :except actions in array" do
386
+ stub(@controller_class).cancan_skipper { {:load => {nil => {:except => [:index, :show]}}} }
387
+ @params.merge!(:action => "index")
388
+ CanCan::ControllerResource.new(@controller).skip?(:load).should be_false
389
+ @params.merge!(:action => "show")
390
+ CanCan::ControllerResource.new(@controller).skip?(:load).should be_false
391
+ @params.merge!(:action => "other_action")
392
+ CanCan::ControllerResource.new(@controller).skip?(:load).should be_true
393
+ CanCan::ControllerResource.new(@controller, :some_resource).skip?(:load).should be_false
394
+ end
395
+
396
+ it "should skip resource behavior :except one action on resource" do
397
+ stub(@controller_class).cancan_skipper { {:authorize => {:project => {:except => :index}}} }
398
+ @params.merge!(:action => "index")
399
+ CanCan::ControllerResource.new(@controller, :project).skip?(:authorize).should be_false
400
+ @params.merge!(:action => "other_action")
401
+ CanCan::ControllerResource.new(@controller).skip?(:authorize).should be_false
402
+ CanCan::ControllerResource.new(@controller, :project).skip?(:authorize).should be_true
403
+ end
404
+
405
+ it "should skip loading and authorization" do
406
+ stub(@controller_class).cancan_skipper { {:authorize => {nil => {}}, :load => {nil => {}}} }
407
+ @params.merge!(:action => "new")
408
+ resource = CanCan::ControllerResource.new(@controller)
409
+ lambda { resource.load_and_authorize_resource }.should_not raise_error
410
+ @controller.instance_variable_get(:@project).should be_nil
411
+ end
412
+ end