cancan 0.2.1 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.rdoc +16 -0
- data/README.rdoc +28 -4
- data/lib/cancan.rb +1 -0
- data/lib/cancan/controller_additions.rb +102 -42
- data/lib/cancan/controller_resource.rb +39 -0
- data/lib/cancan/resource_authorization.rb +27 -11
- data/spec/cancan/controller_additions_spec.rb +12 -10
- data/spec/cancan/controller_resource_spec.rb +43 -0
- data/spec/cancan/resource_authorization_spec.rb +40 -0
- data/spec/spec_helper.rb +4 -0
- metadata +4 -2
data/CHANGELOG.rdoc
CHANGED
@@ -1,3 +1,18 @@
|
|
1
|
+
1.0.0 (Dec 13, 2009)
|
2
|
+
|
3
|
+
* Don't set resource instance variable if it has been set already - see issue #13
|
4
|
+
|
5
|
+
* Allowing :nested option to accept an array for deep nesting
|
6
|
+
|
7
|
+
* Adding :nested option to load resource method - see issue #10
|
8
|
+
|
9
|
+
* Pass :only and :except options to before filters for load/authorize resource methods.
|
10
|
+
|
11
|
+
* Adding :collection and :new options to load_resource method so we can specify behavior of additional actions if needed.
|
12
|
+
|
13
|
+
* BACKWARDS INCOMPATIBLE: turning load and authorize resource methods into class methods which set up the before filter so they can accept additional arguments.
|
14
|
+
|
15
|
+
|
1
16
|
0.2.1 (Nov 26, 2009)
|
2
17
|
|
3
18
|
* many internal refactorings - see issues #11 and #12
|
@@ -6,6 +21,7 @@
|
|
6
21
|
|
7
22
|
* support custom objects (usually symbols) in can definition - see issue #8
|
8
23
|
|
24
|
+
|
9
25
|
0.2.0 (Nov 17, 2009)
|
10
26
|
|
11
27
|
* fix behavior of load_and_authorize_resource for namespaced controllers - see issue #3
|
data/README.rdoc
CHANGED
@@ -10,7 +10,7 @@ See the RDocs[http://rdoc.info/projects/ryanb/cancan] and Wiki[http://wiki.githu
|
|
10
10
|
|
11
11
|
You can set it up as a gem in your environment.rb file.
|
12
12
|
|
13
|
-
config.gem "cancan"
|
13
|
+
config.gem "cancan"
|
14
14
|
|
15
15
|
And then install the gem.
|
16
16
|
|
@@ -21,7 +21,7 @@ Alternatively you can install it as a Rails plugin.
|
|
21
21
|
script/plugin install git://github.com/ryanb/cancan.git
|
22
22
|
|
23
23
|
|
24
|
-
==
|
24
|
+
== Getting Started
|
25
25
|
|
26
26
|
First, define a class called Ability in "models/ability.rb".
|
27
27
|
|
@@ -52,10 +52,10 @@ You can also use these methods in a controller along with the "unauthorized!" me
|
|
52
52
|
unauthorized! if cannot? :read, @article
|
53
53
|
end
|
54
54
|
|
55
|
-
Setting this for every action can be tedious, therefore
|
55
|
+
Setting this for every action can be tedious, therefore the load_and_authorize_resource method is also provided to automatically authorize all actions in a RESTful style resource controller. It will set up a before filter which loads the resource into the instance variable and authorizes it.
|
56
56
|
|
57
57
|
class ArticlesController < ApplicationController
|
58
|
-
|
58
|
+
load_and_authorize_resource
|
59
59
|
|
60
60
|
def show
|
61
61
|
# @article is already loaded
|
@@ -150,6 +150,30 @@ The following aliases are added by default for conveniently mapping common contr
|
|
150
150
|
alias_action :edit, :to => :update
|
151
151
|
|
152
152
|
|
153
|
+
== Authorizing Controller Actions
|
154
|
+
|
155
|
+
As mentioned in the Getting Started section, you can use the +load_and_authorize_resource+ method in your controller to load the resource into an instance variable and authorize it. If you have a nested resource you can specify that as well.
|
156
|
+
|
157
|
+
load_and_authorize_resource :nested => :author
|
158
|
+
|
159
|
+
You can also pass an array to the :+nested+ attribute for deep nesting.
|
160
|
+
|
161
|
+
If you want to customize the loading behavior on certain actions, you can do so in a before filter.
|
162
|
+
|
163
|
+
class BooksController < ApplicationController
|
164
|
+
before_filter :find_book_by_permalink, :only => :show
|
165
|
+
load_and_authorize_resource
|
166
|
+
|
167
|
+
private
|
168
|
+
|
169
|
+
def find_book_by_permalink
|
170
|
+
@book = Book.find_by_permalink!(params[:id)
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
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.
|
175
|
+
|
176
|
+
|
153
177
|
== Assumptions & Configuring
|
154
178
|
|
155
179
|
CanCan makes two assumptions about your application.
|
data/lib/cancan.rb
CHANGED
@@ -5,5 +5,6 @@ module CanCan
|
|
5
5
|
end
|
6
6
|
|
7
7
|
require File.dirname(__FILE__) + '/cancan/ability'
|
8
|
+
require File.dirname(__FILE__) + '/cancan/controller_resource'
|
8
9
|
require File.dirname(__FILE__) + '/cancan/resource_authorization'
|
9
10
|
require File.dirname(__FILE__) + '/cancan/controller_additions'
|
@@ -3,7 +3,109 @@ module CanCan
|
|
3
3
|
# This module is automatically included into all controllers.
|
4
4
|
# It also makes the "can?" and "cannot?" methods available to all views.
|
5
5
|
module ControllerAdditions
|
6
|
+
module ClassMethods
|
7
|
+
# Sets up a before filter which loads and authorizes the current resource. This performs both
|
8
|
+
# load_resource and authorize_resource and accepts the same arguments. See those methods for details.
|
9
|
+
#
|
10
|
+
# class BooksController < ApplicationController
|
11
|
+
# load_and_authorize_resource
|
12
|
+
# end
|
13
|
+
#
|
14
|
+
def load_and_authorize_resource(options = {})
|
15
|
+
before_filter(options.slice(:only, :except)) { |c| ResourceAuthorization.new(c, c.params, options.except(:only, :except)).load_and_authorize_resource }
|
16
|
+
end
|
17
|
+
|
18
|
+
# Sets up a before filter which loads the appropriate model resource into an instance variable.
|
19
|
+
# For example, given an ArticlesController it will load the current article into the @article
|
20
|
+
# instance variable. It does this by either calling Article.find(params[:id]) or
|
21
|
+
# Article.new(params[:article]) depending upon the action. It does nothing for the "index"
|
22
|
+
# action.
|
23
|
+
#
|
24
|
+
# Call this method directly on the controller class.
|
25
|
+
#
|
26
|
+
# class BooksController < ApplicationController
|
27
|
+
# load_resource
|
28
|
+
# end
|
29
|
+
#
|
30
|
+
# A resource is not loaded if the instance variable is already set. This makes it easy to override
|
31
|
+
# the behavior through a before_filter on certain actions.
|
32
|
+
#
|
33
|
+
# class BooksController < ApplicationController
|
34
|
+
# before_filter :find_book_by_permalink, :only => :show
|
35
|
+
# load_resource
|
36
|
+
#
|
37
|
+
# private
|
38
|
+
#
|
39
|
+
# def find_book_by_permalink
|
40
|
+
# @book = Book.find_by_permalink!(params[:id)
|
41
|
+
# end
|
42
|
+
# end
|
43
|
+
#
|
44
|
+
# See load_and_authorize_resource to automatically authorize the resource too.
|
45
|
+
#
|
46
|
+
# Options:
|
47
|
+
# [:+only+]
|
48
|
+
# Only applies before filter to given actions.
|
49
|
+
#
|
50
|
+
# [:+except+]
|
51
|
+
# Does not apply before filter to given actions.
|
52
|
+
#
|
53
|
+
# [:+nested+]
|
54
|
+
# Specify which resource this is nested under.
|
55
|
+
#
|
56
|
+
# load_resource :nested => :author
|
57
|
+
#
|
58
|
+
# Deep nesting can be defined in an array.
|
59
|
+
#
|
60
|
+
# load_resource :nested => [:publisher, :author]
|
61
|
+
#
|
62
|
+
# [:+collection+]
|
63
|
+
# Specify which actions are resource collection actions in addition to :+index+. This
|
64
|
+
# is usually not necessary because it will try to guess depending on if an :+id+
|
65
|
+
# is present in +params+.
|
66
|
+
#
|
67
|
+
# load_resource :collection => [:sort, :list]
|
68
|
+
#
|
69
|
+
# [:+new+]
|
70
|
+
# Specify which actions are new resource actions in addition to :+new+ and :+create+.
|
71
|
+
# Pass an action name into here if you would like to build a new resource instead of
|
72
|
+
# fetch one.
|
73
|
+
#
|
74
|
+
# load_resource :new => :build
|
75
|
+
#
|
76
|
+
def load_resource(options = {})
|
77
|
+
before_filter(options.slice(:only, :except)) { |c| ResourceAuthorization.new(c, c.params, options.except(:only, :except)).load_resource }
|
78
|
+
end
|
79
|
+
|
80
|
+
# Sets up a before filter which authorizes the current resource using the instance variable.
|
81
|
+
# For example, if you have an ArticlesController it will check the @article instance variable
|
82
|
+
# and ensure the user can perform the current action on it. Under the hood it is doing
|
83
|
+
# something like the following.
|
84
|
+
#
|
85
|
+
# unauthorized! if cannot?(params[:action].to_sym, @article || Article)
|
86
|
+
#
|
87
|
+
# Call this method directly on the controller class.
|
88
|
+
#
|
89
|
+
# class BooksController < ApplicationController
|
90
|
+
# authorize_resource
|
91
|
+
# end
|
92
|
+
#
|
93
|
+
# See load_and_authorize_resource to automatically load the resource too.
|
94
|
+
#
|
95
|
+
# Options:
|
96
|
+
# [:+only+]
|
97
|
+
# Only applies before filter to given actions.
|
98
|
+
#
|
99
|
+
# [:+except+]
|
100
|
+
# Does not apply before filter to given actions.
|
101
|
+
#
|
102
|
+
def authorize_resource(options = {})
|
103
|
+
before_filter(options.slice(:only, :except)) { |c| ResourceAuthorization.new(c, c.params, options.except(:only, :except)).authorize_resource }
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
6
107
|
def self.included(base)
|
108
|
+
base.extend ClassMethods
|
7
109
|
base.helper_method :can?, :cannot?
|
8
110
|
end
|
9
111
|
|
@@ -70,48 +172,6 @@ module CanCan
|
|
70
172
|
def cannot?(*args)
|
71
173
|
(@current_ability ||= current_ability).cannot?(*args)
|
72
174
|
end
|
73
|
-
|
74
|
-
# This method loads the appropriate model resource into an instance variable. For example,
|
75
|
-
# given an ArticlesController it will load the current article into the @article instance
|
76
|
-
# variable. It does this by either calling Article.find(params[:id]) or
|
77
|
-
# Article.new(params[:article]) depending upon the action. It does nothing for the "index"
|
78
|
-
# action.
|
79
|
-
#
|
80
|
-
# You would often use this as a before filter in the controller. See
|
81
|
-
# load_and_authorize_resource to handle authorization too.
|
82
|
-
#
|
83
|
-
# before_filter :load_resource
|
84
|
-
#
|
85
|
-
def load_resource
|
86
|
-
ResourceAuthorization.new(self, params).load_resource
|
87
|
-
end
|
88
|
-
|
89
|
-
# Authorizes the resource in the current instance variable. For example,
|
90
|
-
# if you have an ArticlesController it will check the @article instance variable
|
91
|
-
# and ensure the user can perform the current action on it.
|
92
|
-
# Under the hood it is doing something like the following.
|
93
|
-
#
|
94
|
-
# unauthorized! if cannot?(params[:action].to_sym, @article || Article)
|
95
|
-
#
|
96
|
-
# You would often use this as a before filter in the controller.
|
97
|
-
#
|
98
|
-
# before_filter :authorize_resource
|
99
|
-
#
|
100
|
-
# See load_and_authorize_resource to automatically load the resource too.
|
101
|
-
def authorize_resource
|
102
|
-
ResourceAuthorization.new(self, params).authorize_resource
|
103
|
-
end
|
104
|
-
|
105
|
-
# Calls load_resource to load the current resource model into an instance variable.
|
106
|
-
# Then calls authorize_resource to ensure the current user is authorized to access the page.
|
107
|
-
# You would often use this as a before filter in the controller.
|
108
|
-
#
|
109
|
-
# before_filter :load_and_authorize_resource
|
110
|
-
#
|
111
|
-
def load_and_authorize_resource
|
112
|
-
load_resource
|
113
|
-
authorize_resource
|
114
|
-
end
|
115
175
|
end
|
116
176
|
end
|
117
177
|
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module CanCan
|
2
|
+
class ControllerResource # :nodoc:
|
3
|
+
def initialize(controller, name, parent = nil)
|
4
|
+
@controller = controller
|
5
|
+
@name = name
|
6
|
+
@parent = parent
|
7
|
+
end
|
8
|
+
|
9
|
+
def model_class
|
10
|
+
@name.to_s.camelize.constantize
|
11
|
+
end
|
12
|
+
|
13
|
+
def find(id)
|
14
|
+
self.model_instance ||= base.find(id)
|
15
|
+
end
|
16
|
+
|
17
|
+
def build(attributes)
|
18
|
+
if base.kind_of? Class
|
19
|
+
self.model_instance ||= base.new(attributes)
|
20
|
+
else
|
21
|
+
self.model_instance ||= base.build(attributes)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def model_instance
|
26
|
+
@controller.instance_variable_get("@#{@name}")
|
27
|
+
end
|
28
|
+
|
29
|
+
def model_instance=(instance)
|
30
|
+
@controller.instance_variable_set("@#{@name}", instance)
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def base
|
36
|
+
@parent ? @parent.model_instance.send(@name.to_s.pluralize) : model_class
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -2,9 +2,10 @@ module CanCan
|
|
2
2
|
class ResourceAuthorization # :nodoc:
|
3
3
|
attr_reader :params
|
4
4
|
|
5
|
-
def initialize(controller, params)
|
5
|
+
def initialize(controller, params, options = {})
|
6
6
|
@controller = controller
|
7
7
|
@params = params
|
8
|
+
@options = options
|
8
9
|
end
|
9
10
|
|
10
11
|
def load_and_authorize_resource
|
@@ -13,29 +14,44 @@ module CanCan
|
|
13
14
|
end
|
14
15
|
|
15
16
|
def load_resource
|
16
|
-
|
17
|
+
unless collection_actions.include? params[:action].to_sym
|
18
|
+
if new_actions.include? params[:action].to_sym
|
19
|
+
resource.build(params[model_name.to_sym])
|
20
|
+
elsif params[:id]
|
21
|
+
resource.find(params[:id])
|
22
|
+
end
|
23
|
+
end
|
17
24
|
end
|
18
25
|
|
19
26
|
def authorize_resource
|
20
|
-
@controller.unauthorized! if @controller.cannot?(params[:action].to_sym, model_instance || model_class)
|
27
|
+
@controller.unauthorized! if @controller.cannot?(params[:action].to_sym, resource.model_instance || resource.model_class)
|
21
28
|
end
|
22
29
|
|
23
30
|
private
|
24
31
|
|
25
|
-
def
|
26
|
-
|
32
|
+
def resource
|
33
|
+
@resource ||= ControllerResource.new(@controller, model_name, parent_resource)
|
34
|
+
end
|
35
|
+
|
36
|
+
def parent_resource
|
37
|
+
parent = nil
|
38
|
+
[@options[:nested]].flatten.compact.each do |name|
|
39
|
+
parent = ControllerResource.new(@controller, name, parent)
|
40
|
+
parent.find(@params["#{name}_id".to_sym])
|
41
|
+
end
|
42
|
+
parent
|
27
43
|
end
|
28
44
|
|
29
|
-
def
|
30
|
-
|
45
|
+
def model_name
|
46
|
+
params[:controller].split('/').last.singularize
|
31
47
|
end
|
32
48
|
|
33
|
-
def
|
34
|
-
@
|
49
|
+
def collection_actions
|
50
|
+
[:index] + [@options[:collection]].flatten
|
35
51
|
end
|
36
52
|
|
37
|
-
def
|
38
|
-
@
|
53
|
+
def new_actions
|
54
|
+
[:new, :create] + [@options[:new]].flatten
|
39
55
|
end
|
40
56
|
end
|
41
57
|
end
|
@@ -27,19 +27,21 @@ describe CanCan::ControllerAdditions do
|
|
27
27
|
@controller.cannot?(:foo, :bar).should be_true
|
28
28
|
end
|
29
29
|
|
30
|
-
it "should
|
31
|
-
|
32
|
-
@controller
|
30
|
+
it "load_and_authorize_resource should setup a before filter which passes call to ResourceAuthorization" do
|
31
|
+
stub(CanCan::ResourceAuthorization).new(@controller, @controller.params, :foo => :bar).mock!.load_and_authorize_resource
|
32
|
+
mock(@controller_class).before_filter({}) { |options, block| block.call(@controller) }
|
33
|
+
@controller_class.load_and_authorize_resource :foo => :bar
|
33
34
|
end
|
34
35
|
|
35
|
-
it "should
|
36
|
-
|
37
|
-
@controller
|
36
|
+
it "authorize_resource should setup a before filter which passes call to ResourceAuthorization" do
|
37
|
+
stub(CanCan::ResourceAuthorization).new(@controller, @controller.params, :foo => :bar).mock!.authorize_resource
|
38
|
+
mock(@controller_class).before_filter(:except => :show) { |options, block| block.call(@controller) }
|
39
|
+
@controller_class.authorize_resource :foo => :bar, :except => :show
|
38
40
|
end
|
39
41
|
|
40
|
-
it "should
|
41
|
-
|
42
|
-
mock(@controller)
|
43
|
-
@
|
42
|
+
it "load_resource should setup a before filter which passes call to ResourceAuthorization" do
|
43
|
+
stub(CanCan::ResourceAuthorization).new(@controller, @controller.params, :foo => :bar).mock!.load_resource
|
44
|
+
mock(@controller_class).before_filter(:only => [:show, :index]) { |options, block| block.call(@controller) }
|
45
|
+
@controller_class.load_resource :foo => :bar, :only => [:show, :index]
|
44
46
|
end
|
45
47
|
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
|
3
|
+
describe CanCan::ControllerResource do
|
4
|
+
before(:each) do
|
5
|
+
@controller = Object.new
|
6
|
+
end
|
7
|
+
|
8
|
+
it "should determine model class by constantizing give name" do
|
9
|
+
CanCan::ControllerResource.new(@controller, :ability).model_class.should == Ability
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should fetch model through model class and assign it to the instance" do
|
13
|
+
stub(Ability).find(123) { :some_ability }
|
14
|
+
CanCan::ControllerResource.new(@controller, :ability).find(123)
|
15
|
+
@controller.instance_variable_get(:@ability).should == :some_ability
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should fetch model through parent and assign it to the instance" do
|
19
|
+
parent = Object.new
|
20
|
+
stub(parent).model_instance.stub!.abilities.stub!.find(123) { :some_ability }
|
21
|
+
CanCan::ControllerResource.new(@controller, :ability, parent).find(123)
|
22
|
+
@controller.instance_variable_get(:@ability).should == :some_ability
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should build model through model class and assign it to the instance" do
|
26
|
+
stub(Ability).new(123) { :some_ability }
|
27
|
+
CanCan::ControllerResource.new(@controller, :ability).build(123)
|
28
|
+
@controller.instance_variable_get(:@ability).should == :some_ability
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should build model through parent and assign it to the instance" do
|
32
|
+
parent = Object.new
|
33
|
+
stub(parent).model_instance.stub!.abilities.stub!.build(123) { :some_ability }
|
34
|
+
CanCan::ControllerResource.new(@controller, :ability, parent).build(123)
|
35
|
+
@controller.instance_variable_get(:@ability).should == :some_ability
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should not load resource if instance variable is already provided" do
|
39
|
+
@controller.instance_variable_set(:@ability, :some_ability)
|
40
|
+
CanCan::ControllerResource.new(@controller, :ability).find(123)
|
41
|
+
@controller.instance_variable_get(:@ability).should == :some_ability
|
42
|
+
end
|
43
|
+
end
|
@@ -56,4 +56,44 @@ describe CanCan::ResourceAuthorization do
|
|
56
56
|
authorization.authorize_resource
|
57
57
|
}.should raise_error(CanCan::AccessDenied)
|
58
58
|
end
|
59
|
+
|
60
|
+
it "should call load_resource and authorize_resource for load_and_authorize_resource" do
|
61
|
+
authorization = CanCan::ResourceAuthorization.new(@controller, :controller => "abilities", :action => "show")
|
62
|
+
mock(authorization).load_resource
|
63
|
+
mock(authorization).authorize_resource
|
64
|
+
authorization.load_and_authorize_resource
|
65
|
+
end
|
66
|
+
|
67
|
+
it "should not build a resource when on custom collection action" do
|
68
|
+
authorization = CanCan::ResourceAuthorization.new(@controller, {:controller => "abilities", :action => "sort"}, {:collection => [:sort, :list]})
|
69
|
+
authorization.load_resource
|
70
|
+
@controller.instance_variable_get(:@ability).should be_nil
|
71
|
+
end
|
72
|
+
|
73
|
+
it "should build a resource when on custom new action even when params[:id] exists" do
|
74
|
+
stub(Ability).new(nil) { :some_resource }
|
75
|
+
authorization = CanCan::ResourceAuthorization.new(@controller, {:controller => "abilities", :action => "build", :id => 123}, {:new => :build})
|
76
|
+
authorization.load_resource
|
77
|
+
@controller.instance_variable_get(:@ability).should == :some_resource
|
78
|
+
end
|
79
|
+
|
80
|
+
it "should not try to load resource for other action if params[:id] is undefined" do
|
81
|
+
authorization = CanCan::ResourceAuthorization.new(@controller, :controller => "abilities", :action => "list")
|
82
|
+
authorization.load_resource
|
83
|
+
@controller.instance_variable_get(:@ability).should be_nil
|
84
|
+
end
|
85
|
+
|
86
|
+
it "should load nested resource and fetch other resource through the association" do
|
87
|
+
stub(Person).find(456).stub!.abilities.stub!.find(123) { :some_ability }
|
88
|
+
authorization = CanCan::ResourceAuthorization.new(@controller, {:controller => "abilities", :action => "show", :id => 123, :person_id => 456}, {:nested => :person})
|
89
|
+
authorization.load_resource
|
90
|
+
@controller.instance_variable_get(:@ability).should == :some_ability
|
91
|
+
end
|
92
|
+
|
93
|
+
it "should load nested resource and build resource through a deep association" do
|
94
|
+
stub(Person).find(456).stub!.behaviors.stub!.find(789).stub!.abilities.stub!.build(nil) { :some_ability }
|
95
|
+
authorization = CanCan::ResourceAuthorization.new(@controller, {:controller => "abilities", :action => "new", :person_id => 456, :behavior_id => 789}, {:nested => [:person, :behavior]})
|
96
|
+
authorization.load_resource
|
97
|
+
@controller.instance_variable_get(:@ability).should == :some_ability
|
98
|
+
end
|
59
99
|
end
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cancan
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ryan Bates
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-
|
12
|
+
date: 2009-12-13 00:00:00 -08:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|
@@ -26,10 +26,12 @@ extra_rdoc_files:
|
|
26
26
|
files:
|
27
27
|
- lib/cancan/ability.rb
|
28
28
|
- lib/cancan/controller_additions.rb
|
29
|
+
- lib/cancan/controller_resource.rb
|
29
30
|
- lib/cancan/resource_authorization.rb
|
30
31
|
- lib/cancan.rb
|
31
32
|
- spec/cancan/ability_spec.rb
|
32
33
|
- spec/cancan/controller_additions_spec.rb
|
34
|
+
- spec/cancan/controller_resource_spec.rb
|
33
35
|
- spec/cancan/resource_authorization_spec.rb
|
34
36
|
- spec/spec_helper.rb
|
35
37
|
- LICENSE
|