cancan 1.4.1 → 1.5.0

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 (36) hide show
  1. data/CHANGELOG.rdoc +21 -0
  2. data/Gemfile +17 -0
  3. data/LICENSE +1 -1
  4. data/README.rdoc +20 -90
  5. data/Rakefile +8 -0
  6. data/lib/cancan/ability.rb +24 -26
  7. data/lib/cancan/controller_additions.rb +50 -0
  8. data/lib/cancan/controller_resource.rb +33 -15
  9. data/lib/cancan/exceptions.rb +3 -0
  10. data/lib/cancan/model_adapters/abstract_adapter.rb +40 -0
  11. data/lib/cancan/model_adapters/active_record_adapter.rb +119 -0
  12. data/lib/cancan/model_adapters/data_mapper_adapter.rb +33 -0
  13. data/lib/cancan/model_adapters/default_adapter.rb +7 -0
  14. data/lib/cancan/model_adapters/mongoid_adapter.rb +41 -0
  15. data/lib/cancan/{active_record_additions.rb → model_additions.rb} +5 -16
  16. data/lib/cancan/{can_definition.rb → rule.rb} +29 -25
  17. data/lib/cancan.rb +8 -3
  18. data/lib/generators/cancan/ability/USAGE +4 -0
  19. data/lib/generators/cancan/ability/ability_generator.rb +11 -0
  20. data/lib/generators/cancan/ability/templates/ability.rb +28 -0
  21. data/spec/README.rdoc +28 -0
  22. data/spec/cancan/ability_spec.rb +11 -3
  23. data/spec/cancan/controller_additions_spec.rb +30 -0
  24. data/spec/cancan/controller_resource_spec.rb +68 -2
  25. data/spec/cancan/inherited_resource_spec.rb +3 -1
  26. data/spec/cancan/model_adapters/active_record_adapter_spec.rb +185 -0
  27. data/spec/cancan/model_adapters/data_mapper_adapter_spec.rb +115 -0
  28. data/spec/cancan/model_adapters/default_adapter_spec.rb +7 -0
  29. data/spec/cancan/model_adapters/mongoid_adapter_spec.rb +168 -0
  30. data/spec/cancan/rule_spec.rb +39 -0
  31. data/spec/spec_helper.rb +2 -24
  32. metadata +24 -16
  33. data/lib/cancan/query.rb +0 -97
  34. data/spec/cancan/active_record_additions_spec.rb +0 -75
  35. data/spec/cancan/can_definition_spec.rb +0 -57
  36. data/spec/cancan/query_spec.rb +0 -107
@@ -0,0 +1,115 @@
1
+ if ENV["MODEL_ADAPTER"] == "data_mapper"
2
+ require "spec_helper"
3
+
4
+ DataMapper.setup(:default, 'sqlite::memory:')
5
+
6
+ class Article
7
+ include DataMapper::Resource
8
+ property :id, Serial
9
+ property :published, Boolean, :default => false
10
+ property :secret, Boolean, :default => false
11
+ property :priority, Integer
12
+ has n, :comments
13
+ end
14
+
15
+ class Comment
16
+ include DataMapper::Resource
17
+ property :id, Serial
18
+ property :spam, Boolean, :default => false
19
+ belongs_to :article
20
+ end
21
+
22
+ DataMapper.finalize
23
+ DataMapper.auto_migrate!
24
+
25
+ describe CanCan::ModelAdapters::DataMapperAdapter do
26
+ before(:each) do
27
+ Article.destroy
28
+ Comment.destroy
29
+ @ability = Object.new
30
+ @ability.extend(CanCan::Ability)
31
+ end
32
+
33
+ it "should be for only data mapper classes" do
34
+ CanCan::ModelAdapters::DataMapperAdapter.should_not be_for_class(Object)
35
+ CanCan::ModelAdapters::DataMapperAdapter.should be_for_class(Article)
36
+ CanCan::ModelAdapters::AbstractAdapter.adapter_class(Article).should == CanCan::ModelAdapters::DataMapperAdapter
37
+ end
38
+
39
+ it "should not fetch any records when no abilities are defined" do
40
+ Article.create
41
+ Article.accessible_by(@ability).should be_empty
42
+ end
43
+
44
+ it "should fetch all articles when one can read all" do
45
+ @ability.can :read, Article
46
+ article = Article.create
47
+ Article.accessible_by(@ability).should == [article]
48
+ end
49
+
50
+ it "should fetch only the articles that are published" do
51
+ @ability.can :read, Article, :published => true
52
+ article1 = Article.create(:published => true)
53
+ article2 = Article.create(:published => false)
54
+ Article.accessible_by(@ability).should == [article1]
55
+ end
56
+
57
+ it "should fetch any articles which are published or secret" do
58
+ @ability.can :read, Article, :published => true
59
+ @ability.can :read, Article, :secret => true
60
+ article1 = Article.create(:published => true, :secret => false)
61
+ article2 = Article.create(:published => true, :secret => true)
62
+ article3 = Article.create(:published => false, :secret => true)
63
+ article4 = Article.create(:published => false, :secret => false)
64
+ Article.accessible_by(@ability).should == [article1, article2, article3]
65
+ end
66
+
67
+ it "should fetch only the articles that are published and not secret" do
68
+ pending "the `cannot` may require some custom SQL, maybe abstract out from Active Record adapter"
69
+ @ability.can :read, Article, :published => true
70
+ @ability.cannot :read, Article, :secret => true
71
+ article1 = Article.create(:published => true, :secret => false)
72
+ article2 = Article.create(:published => true, :secret => true)
73
+ article3 = Article.create(:published => false, :secret => true)
74
+ article4 = Article.create(:published => false, :secret => false)
75
+ Article.accessible_by(@ability).should == [article1]
76
+ end
77
+
78
+ it "should only read comments for articles which are published" do
79
+ @ability.can :read, Comment, :article => { :published => true }
80
+ comment1 = Comment.create(:article => Article.create!(:published => true))
81
+ comment2 = Comment.create(:article => Article.create!(:published => false))
82
+ Comment.accessible_by(@ability).should == [comment1]
83
+ end
84
+
85
+ it "should allow conditions in SQL and merge with hash conditions" do
86
+ @ability.can :read, Article, :published => true
87
+ @ability.can :read, Article, ["secret=?", true]
88
+ article1 = Article.create(:published => true, :secret => false)
89
+ article4 = Article.create(:published => false, :secret => false)
90
+ Article.accessible_by(@ability).should == [article1]
91
+ end
92
+
93
+ it "should match gt comparison" do
94
+ @ability.can :read, Article, :priority.gt => 3
95
+ article1 = Article.create(:priority => 4)
96
+ article2 = Article.create(:priority => 3)
97
+ Article.accessible_by(@ability).should == [article1]
98
+ @ability.should be_able_to(:read, article1)
99
+ @ability.should_not be_able_to(:read, article2)
100
+ end
101
+
102
+ it "should match gte comparison" do
103
+ @ability.can :read, Article, :priority.gte => 3
104
+ article1 = Article.create(:priority => 4)
105
+ article2 = Article.create(:priority => 3)
106
+ article3 = Article.create(:priority => 2)
107
+ Article.accessible_by(@ability).should == [article1, article2]
108
+ @ability.should be_able_to(:read, article1)
109
+ @ability.should be_able_to(:read, article2)
110
+ @ability.should_not be_able_to(:read, article3)
111
+ end
112
+
113
+ # TODO: add more comparison specs
114
+ end
115
+ end
@@ -0,0 +1,7 @@
1
+ require "spec_helper"
2
+
3
+ describe CanCan::ModelAdapters::DefaultAdapter do
4
+ it "should be default for generic classes" do
5
+ CanCan::ModelAdapters::AbstractAdapter.adapter_class(Object).should == CanCan::ModelAdapters::DefaultAdapter
6
+ end
7
+ end
@@ -0,0 +1,168 @@
1
+ if ENV["MODEL_ADAPTER"] == "mongoid"
2
+ require "spec_helper"
3
+
4
+ class MongoidCategory
5
+ include Mongoid::Document
6
+
7
+ references_many :mongoid_projects
8
+ end
9
+
10
+ class MongoidProject
11
+ include Mongoid::Document
12
+
13
+ referenced_in :mongoid_category
14
+ end
15
+
16
+ Mongoid.configure do |config|
17
+ config.master = Mongo::Connection.new('127.0.0.1', 27017).db("cancan_mongoid_spec")
18
+ end
19
+
20
+ describe CanCan::ModelAdapters::MongoidAdapter do
21
+ context "Mongoid defined" do
22
+ before(:each) do
23
+ @ability = Object.new
24
+ @ability.extend(CanCan::Ability)
25
+ end
26
+
27
+ after(:each) do
28
+ Mongoid.master.collections.select do |collection|
29
+ collection.name !~ /system/
30
+ end.each(&:drop)
31
+ end
32
+
33
+ it "should be for only Mongoid classes" do
34
+ CanCan::ModelAdapters::MongoidAdapter.should_not be_for_class(Object)
35
+ CanCan::ModelAdapters::MongoidAdapter.should be_for_class(MongoidProject)
36
+ CanCan::ModelAdapters::AbstractAdapter.adapter_class(MongoidProject).should == CanCan::ModelAdapters::MongoidAdapter
37
+ end
38
+
39
+ it "should compare properties on mongoid documents with the conditions hash" do
40
+ model = MongoidProject.new
41
+ @ability.can :read, MongoidProject, :id => model.id
42
+ @ability.should be_able_to(:read, model)
43
+ end
44
+
45
+ it "should return [] when no ability is defined so no records are found" do
46
+ MongoidProject.create(:title => 'Sir')
47
+ MongoidProject.create(:title => 'Lord')
48
+ MongoidProject.create(:title => 'Dude')
49
+
50
+ MongoidProject.accessible_by(@ability, :read).entries.should == []
51
+ end
52
+
53
+ it "should return the correct records based on the defined ability" do
54
+ @ability.can :read, MongoidProject, :title => "Sir"
55
+ sir = MongoidProject.create(:title => 'Sir')
56
+ lord = MongoidProject.create(:title => 'Lord')
57
+ dude = MongoidProject.create(:title => 'Dude')
58
+
59
+ MongoidProject.accessible_by(@ability, :read).should == [sir]
60
+ end
61
+
62
+ it "should return everything when the defined ability is manage all" do
63
+ @ability.can :manage, :all
64
+ sir = MongoidProject.create(:title => 'Sir')
65
+ lord = MongoidProject.create(:title => 'Lord')
66
+ dude = MongoidProject.create(:title => 'Dude')
67
+
68
+ MongoidProject.accessible_by(@ability, :read).entries.should == [sir, lord, dude]
69
+ end
70
+
71
+
72
+ describe "Mongoid::Criteria where clause Symbol extensions using MongoDB expressions" do
73
+ it "should handle :field.in" do
74
+ obj = MongoidProject.create(:title => 'Sir')
75
+ @ability.can :read, MongoidProject, :title.in => ["Sir", "Madam"]
76
+ @ability.can?(:read, obj).should == true
77
+ MongoidProject.accessible_by(@ability, :read).should == [obj]
78
+
79
+ obj2 = MongoidProject.create(:title => 'Lord')
80
+ @ability.can?(:read, obj2).should == false
81
+ end
82
+
83
+ describe "activates only when there are Criteria in the hash" do
84
+ it "Calls where on the model class when there are criteria" do
85
+ obj = MongoidProject.create(:title => 'Bird')
86
+ @conditions = {:title.nin => ["Fork", "Spoon"]}
87
+
88
+ @ability.can :read, MongoidProject, @conditions
89
+ @ability.should be_able_to(:read, obj)
90
+ end
91
+ it "Calls the base version if there are no mongoid criteria" do
92
+ obj = MongoidProject.new(:title => 'Bird')
93
+ @conditions = {:id => obj.id}
94
+ @ability.can :read, MongoidProject, @conditions
95
+ @ability.should be_able_to(:read, obj)
96
+ end
97
+ end
98
+
99
+ it "should handle :field.nin" do
100
+ obj = MongoidProject.create(:title => 'Sir')
101
+ @ability.can :read, MongoidProject, :title.nin => ["Lord", "Madam"]
102
+ @ability.can?(:read, obj).should == true
103
+ MongoidProject.accessible_by(@ability, :read).should == [obj]
104
+
105
+ obj2 = MongoidProject.create(:title => 'Lord')
106
+ @ability.can?(:read, obj2).should == false
107
+ end
108
+
109
+ it "should handle :field.size" do
110
+ obj = MongoidProject.create(:titles => ['Palatin', 'Margrave'])
111
+ @ability.can :read, MongoidProject, :titles.size => 2
112
+ @ability.can?(:read, obj).should == true
113
+ MongoidProject.accessible_by(@ability, :read).should == [obj]
114
+
115
+ obj2 = MongoidProject.create(:titles => ['Palatin', 'Margrave', 'Marquis'])
116
+ @ability.can?(:read, obj2).should == false
117
+ end
118
+
119
+ it "should handle :field.exists" do
120
+ obj = MongoidProject.create(:titles => ['Palatin', 'Margrave'])
121
+ @ability.can :read, MongoidProject, :titles.exists => true
122
+ @ability.can?(:read, obj).should == true
123
+ MongoidProject.accessible_by(@ability, :read).should == [obj]
124
+
125
+ obj2 = MongoidProject.create
126
+ @ability.can?(:read, obj2).should == false
127
+ end
128
+
129
+ it "should handle :field.gt" do
130
+ obj = MongoidProject.create(:age => 50)
131
+ @ability.can :read, MongoidProject, :age.gt => 45
132
+ @ability.can?(:read, obj).should == true
133
+ MongoidProject.accessible_by(@ability, :read).should == [obj]
134
+
135
+ obj2 = MongoidProject.create(:age => 40)
136
+ @ability.can?(:read, obj2).should == false
137
+ end
138
+
139
+ it "should handle instance not saved to database" do
140
+ obj = MongoidProject.new(:title => 'Sir')
141
+ @ability.can :read, MongoidProject, :title.in => ["Sir", "Madam"]
142
+ @ability.can?(:read, obj).should == true
143
+
144
+ # accessible_by only returns saved records
145
+ MongoidProject.accessible_by(@ability, :read).entries.should == []
146
+
147
+ obj2 = MongoidProject.new(:title => 'Lord')
148
+ @ability.can?(:read, obj2).should == false
149
+ end
150
+ end
151
+
152
+ it "should call where with matching ability conditions" do
153
+ obj = MongoidProject.create(:foo => {:bar => 1})
154
+ @ability.can :read, MongoidProject, :foo => {:bar => 1}
155
+ MongoidProject.accessible_by(@ability, :read).entries.first.should == obj
156
+ end
157
+
158
+ it "should not allow to fetch records when ability with just block present" do
159
+ @ability.can :read, MongoidProject do
160
+ false
161
+ end
162
+ lambda {
163
+ MongoidProject.accessible_by(@ability)
164
+ }.should raise_error(CanCan::Error)
165
+ end
166
+ end
167
+ end
168
+ end
@@ -0,0 +1,39 @@
1
+ require "spec_helper"
2
+
3
+ # Most of Rule functionality is tested in Ability specs
4
+ describe CanCan::Rule do
5
+ before(:each) do
6
+ @conditions = {}
7
+ @rule = CanCan::Rule.new(true, :read, Integer, @conditions, nil)
8
+ end
9
+
10
+ it "should return no association joins if none exist" do
11
+ @rule.associations_hash.should == {}
12
+ end
13
+
14
+ it "should return no association for joins if just attributes" do
15
+ @conditions[:foo] = :bar
16
+ @rule.associations_hash.should == {}
17
+ end
18
+
19
+ it "should return single association for joins" do
20
+ @conditions[:foo] = {:bar => 1}
21
+ @rule.associations_hash.should == {:foo => {}}
22
+ end
23
+
24
+ it "should return multiple associations for joins" do
25
+ @conditions[:foo] = {:bar => 1}
26
+ @conditions[:test] = {1 => 2}
27
+ @rule.associations_hash.should == {:foo => {}, :test => {}}
28
+ end
29
+
30
+ it "should return nested associations for joins" do
31
+ @conditions[:foo] = {:bar => {1 => 2}}
32
+ @rule.associations_hash.should == {:foo => {:bar => {}}}
33
+ end
34
+
35
+ it "should return no association joins if conditions is nil" do
36
+ rule = CanCan::Rule.new(true, :read, Integer, nil, nil)
37
+ rule.associations_hash.should == {}
38
+ end
39
+ end
data/spec/spec_helper.rb CHANGED
@@ -1,6 +1,8 @@
1
1
  require 'rubygems'
2
2
  require 'bundler/setup'
3
+
3
4
  Bundler.require(:default)
5
+
4
6
  require 'supermodel' # shouldn't Bundler do this already?
5
7
  require 'active_support/all'
6
8
  require 'matchers'
@@ -27,28 +29,4 @@ end
27
29
 
28
30
  class Project < SuperModel::Base
29
31
  belongs_to :category
30
-
31
- class << self
32
- protected
33
-
34
- def sanitize_sql(hash_cond)
35
- case hash_cond
36
- when Hash
37
- sanitize_hash(hash_cond).join(' AND ')
38
- when Array
39
- hash_cond.shift.gsub('?'){"#{hash_cond.shift.inspect}"}
40
- when String then hash_cond
41
- end
42
- end
43
-
44
- def sanitize_hash(hash)
45
- hash.map do |name, value|
46
- if Hash === value
47
- sanitize_hash(value).map{|cond| "#{name}.#{cond}"}
48
- else
49
- "#{name}=#{value}"
50
- end
51
- end.flatten
52
- end
53
- end
54
32
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cancan
3
3
  version: !ruby/object:Gem::Version
4
- hash: 5
4
+ hash: 3
5
5
  prerelease: false
6
6
  segments:
7
7
  - 1
8
- - 4
9
- - 1
10
- version: 1.4.1
8
+ - 5
9
+ - 0
10
+ version: 1.5.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Ryan Bates
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2010-11-12 00:00:00 -08:00
18
+ date: 2011-01-11 00:00:00 -08:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -26,14 +26,12 @@ dependencies:
26
26
  requirements:
27
27
  - - ~>
28
28
  - !ruby/object:Gem::Version
29
- hash: 62196431
29
+ hash: 11
30
30
  segments:
31
31
  - 2
32
+ - 1
32
33
  - 0
33
- - 0
34
- - beta
35
- - 22
36
- version: 2.0.0.beta.22
34
+ version: 2.1.0
37
35
  type: :development
38
36
  version_requirements: *id001
39
37
  - !ruby/object:Gem::Dependency
@@ -94,25 +92,35 @@ extra_rdoc_files: []
94
92
 
95
93
  files:
96
94
  - lib/cancan/ability.rb
97
- - lib/cancan/active_record_additions.rb
98
- - lib/cancan/can_definition.rb
99
95
  - lib/cancan/controller_additions.rb
100
96
  - lib/cancan/controller_resource.rb
101
97
  - lib/cancan/exceptions.rb
102
98
  - lib/cancan/inherited_resource.rb
103
99
  - lib/cancan/matchers.rb
104
- - lib/cancan/query.rb
100
+ - lib/cancan/model_adapters/abstract_adapter.rb
101
+ - lib/cancan/model_adapters/active_record_adapter.rb
102
+ - lib/cancan/model_adapters/data_mapper_adapter.rb
103
+ - lib/cancan/model_adapters/default_adapter.rb
104
+ - lib/cancan/model_adapters/mongoid_adapter.rb
105
+ - lib/cancan/model_additions.rb
106
+ - lib/cancan/rule.rb
105
107
  - lib/cancan.rb
108
+ - lib/generators/cancan/ability/ability_generator.rb
109
+ - lib/generators/cancan/ability/templates/ability.rb
110
+ - lib/generators/cancan/ability/USAGE
106
111
  - spec/cancan/ability_spec.rb
107
- - spec/cancan/active_record_additions_spec.rb
108
- - spec/cancan/can_definition_spec.rb
109
112
  - spec/cancan/controller_additions_spec.rb
110
113
  - spec/cancan/controller_resource_spec.rb
111
114
  - spec/cancan/exceptions_spec.rb
112
115
  - spec/cancan/inherited_resource_spec.rb
113
116
  - spec/cancan/matchers_spec.rb
114
- - spec/cancan/query_spec.rb
117
+ - spec/cancan/model_adapters/active_record_adapter_spec.rb
118
+ - spec/cancan/model_adapters/data_mapper_adapter_spec.rb
119
+ - spec/cancan/model_adapters/default_adapter_spec.rb
120
+ - spec/cancan/model_adapters/mongoid_adapter_spec.rb
121
+ - spec/cancan/rule_spec.rb
115
122
  - spec/matchers.rb
123
+ - spec/README.rdoc
116
124
  - spec/spec.opts
117
125
  - spec/spec_helper.rb
118
126
  - CHANGELOG.rdoc
data/lib/cancan/query.rb DELETED
@@ -1,97 +0,0 @@
1
- module CanCan
2
-
3
- # Generates the sql conditions and association joins for use in ActiveRecord queries.
4
- # Normally you will not use this class directly, but instead through ActiveRecordAdditions#accessible_by.
5
- class Query
6
- def initialize(sanitizer, can_definitions)
7
- @sanitizer = sanitizer
8
- @can_definitions = can_definitions
9
- end
10
-
11
- # Returns conditions intended to be used inside a database query. Normally you will not call this
12
- # method directly, but instead go through ActiveRecordAdditions#accessible_by.
13
- #
14
- # If there is only one "can" definition, a hash of conditions will be returned matching the one defined.
15
- #
16
- # can :manage, User, :id => 1
17
- # query(:manage, User).conditions # => { :id => 1 }
18
- #
19
- # If there are multiple "can" definitions, a SQL string will be returned to handle complex cases.
20
- #
21
- # can :manage, User, :id => 1
22
- # can :manage, User, :manager_id => 1
23
- # cannot :manage, User, :self_managed => true
24
- # query(:manage, User).conditions # => "not (self_managed = 't') AND ((manager_id = 1) OR (id = 1))"
25
- #
26
- def conditions
27
- if @can_definitions.size == 1 && @can_definitions.first.base_behavior
28
- # Return the conditions directly if there's just one definition
29
- @can_definitions.first.tableized_conditions
30
- else
31
- @can_definitions.reverse.inject(false_sql) do |sql, can_definition|
32
- merge_conditions(sql, can_definition.tableized_conditions, can_definition.base_behavior)
33
- end
34
- end
35
- end
36
-
37
- # Returns the associations used in conditions for the :joins option of a search.
38
- # See ActiveRecordAdditions#accessible_by for use in Active Record.
39
- def joins
40
- joins_hash = {}
41
- @can_definitions.each do |can_definition|
42
- merge_joins(joins_hash, can_definition.associations_hash)
43
- end
44
- clean_joins(joins_hash) unless joins_hash.empty?
45
- end
46
-
47
- private
48
-
49
- def merge_conditions(sql, conditions_hash, behavior)
50
- if conditions_hash.blank?
51
- behavior ? true_sql : false_sql
52
- else
53
- conditions = sanitize_sql(conditions_hash)
54
- case sql
55
- when true_sql
56
- behavior ? true_sql : "not (#{conditions})"
57
- when false_sql
58
- behavior ? conditions : false_sql
59
- else
60
- behavior ? "(#{conditions}) OR (#{sql})" : "not (#{conditions}) AND (#{sql})"
61
- end
62
- end
63
- end
64
-
65
- def false_sql
66
- sanitize_sql(['?=?', true, false])
67
- end
68
-
69
- def true_sql
70
- sanitize_sql(['?=?', true, true])
71
- end
72
-
73
- def sanitize_sql(conditions)
74
- @sanitizer.send(:sanitize_sql, conditions)
75
- end
76
-
77
- # Takes two hashes and does a deep merge.
78
- def merge_joins(base, add)
79
- add.each do |name, nested|
80
- if base[name].is_a?(Hash) && !nested.empty?
81
- merge_joins(base[name], nested)
82
- else
83
- base[name] = nested
84
- end
85
- end
86
- end
87
-
88
- # Removes empty hashes and moves everything into arrays.
89
- def clean_joins(joins_hash)
90
- joins = []
91
- joins_hash.each do |name, nested|
92
- joins << (nested.empty? ? name : {name => clean_joins(nested)})
93
- end
94
- joins
95
- end
96
- end
97
- end
@@ -1,75 +0,0 @@
1
- require "spec_helper"
2
-
3
- describe CanCan::ActiveRecordAdditions do
4
- before(:each) do
5
- @model_class = Class.new(Project)
6
- stub(@model_class).scoped { :scoped_stub }
7
- @model_class.send(:include, CanCan::ActiveRecordAdditions)
8
- @ability = Object.new
9
- @ability.extend(CanCan::Ability)
10
- end
11
-
12
- it "should call where('true=false') when no ability is defined so no records are found" do
13
- stub(@model_class).joins { true } # just so it responds to .joins as well
14
- stub(@model_class).where('true=false').stub!.joins(nil) { :no_match }
15
- @model_class.accessible_by(@ability, :read).should == :no_match
16
- end
17
-
18
- it "should call where with matching ability conditions" do
19
- @ability.can :read, @model_class, :foo => {:bar => 1}
20
- stub(@model_class).joins { true } # just so it responds to .joins as well
21
- stub(@model_class).where(:foos => { :bar => 1 }).stub!.joins([:foo]) { :found_records }
22
- @model_class.accessible_by(@ability, :read).should == :found_records
23
- end
24
-
25
- it "should default to :read ability and use scoped when where isn't available" do
26
- @ability.can :read, @model_class, :foo => {:bar => 1}
27
- stub(@model_class).scoped(:conditions => {:foos => {:bar => 1}}, :joins => [:foo]) { :found_records }
28
- @model_class.accessible_by(@ability).should == :found_records
29
- end
30
-
31
- it "should merge association joins and sanitize conditions" do
32
- @ability.can :read, @model_class, :foo => {:bar => 1}
33
- @ability.can :read, @model_class, :too => {:car => 1, :far => {:bar => 1}}
34
-
35
- condition_variants = [
36
- '(toos.fars.bar=1 AND toos.car=1) OR (foos.bar=1)', # faked sql sanitizer is stupid ;-)
37
- '(toos.car=1 AND toos.fars.bar=1) OR (foos.bar=1)'
38
- ]
39
- joins_variants = [
40
- [:foo, {:too => [:far]}],
41
- [{:too => [:far]}, :foo]
42
- ]
43
-
44
- condition_variants.each do |condition|
45
- joins_variants.each do |joins|
46
- stub(@model_class).scoped( :conditions => condition, :joins => joins ) { :found_records }
47
- end
48
- end
49
- # @ability.conditions(:read, @model_class).should == '(too.car=1 AND too.far.bar=1) OR (foo.bar=1)'
50
- # @ability.associations_hash(:read, @model_class).should == [{:too => [:far]}, :foo]
51
- @model_class.accessible_by(@ability).should == :found_records
52
- end
53
-
54
- it "should allow to define sql conditions by not hash" do
55
- @ability.can :read, @model_class, :foo => 1
56
- @ability.can :read, @model_class, ['bar = ?', 1]
57
- stub(@model_class).scoped( :conditions => '(bar = 1) OR (foo=1)', :joins => nil ) { :found_records }
58
- stub(@model_class).scoped{|*args| args.inspect}
59
- @model_class.accessible_by(@ability).should == :found_records
60
- end
61
-
62
- it "should not allow to fetch records when ability with just block present" do
63
- @ability.can :read, @model_class do false end
64
- lambda {
65
- @model_class.accessible_by(@ability)
66
- }.should raise_error(CanCan::Error)
67
- end
68
-
69
- it "should not allow to check ability on object when nonhash sql ability definition without block present" do
70
- @ability.can :read, @model_class, ['bar = ?', 1]
71
- lambda {
72
- @ability.can? :read, @model_class.new
73
- }.should raise_error(CanCan::Error)
74
- end
75
- end
@@ -1,57 +0,0 @@
1
- require "spec_helper"
2
-
3
- # Most of CanDefinition functionality is tested in Ability specs
4
- describe CanCan::CanDefinition do
5
- before(:each) do
6
- @conditions = {}
7
- @can = CanCan::CanDefinition.new(true, :read, Integer, @conditions, nil)
8
- end
9
-
10
- it "should return no association joins if none exist" do
11
- @can.associations_hash.should == {}
12
- end
13
-
14
- it "should return no association for joins if just attributes" do
15
- @conditions[:foo] = :bar
16
- @can.associations_hash.should == {}
17
- end
18
-
19
- it "should return single association for joins" do
20
- @conditions[:foo] = {:bar => 1}
21
- @can.associations_hash.should == {:foo => {}}
22
- end
23
-
24
- it "should return multiple associations for joins" do
25
- @conditions[:foo] = {:bar => 1}
26
- @conditions[:test] = {1 => 2}
27
- @can.associations_hash.should == {:foo => {}, :test => {}}
28
- end
29
-
30
- it "should return nested associations for joins" do
31
- @conditions[:foo] = {:bar => {1 => 2}}
32
- @can.associations_hash.should == {:foo => {:bar => {}}}
33
- end
34
-
35
- it "should tableize correctly for absurdly complex permissions" do
36
- @conditions[:unit] = {:property=>{:landlord=>{:weasle_id=>560}}}
37
- @conditions[:test] = 1
38
- @can.tableized_conditions.should == {:units => {:properties => {:landlords=>{:weasle_id=>560}}}, :test => 1}
39
- end
40
-
41
- it "should tableize correctly for complex permissions" do
42
- @conditions[:unit] = {:property=>{:landlord_id=>560}}
43
- @conditions[:test] = 1
44
- @can.tableized_conditions.should == {:units => {:properties => {:landlord_id=>560}}, :test => 1}
45
- end
46
-
47
- it "should return table names in conditions for association joins" do
48
- @conditions[:foo] = {:bar => 1}
49
- @conditions[:test] = 1
50
- @can.tableized_conditions.should == {:foos => {:bar => 1}, :test => 1}
51
- end
52
-
53
- it "should return no association joins if conditions is nil" do
54
- can = CanCan::CanDefinition.new(true, :read, Integer, nil, nil)
55
- can.associations_hash.should == {}
56
- end
57
- end