cancan 1.4.1 → 1.5.0.beta1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.rdoc +21 -0
- data/Gemfile +17 -0
- data/LICENSE +1 -1
- data/README.rdoc +16 -77
- data/Rakefile +8 -0
- data/lib/cancan.rb +8 -3
- data/lib/cancan/ability.rb +24 -26
- data/lib/cancan/controller_additions.rb +50 -0
- data/lib/cancan/controller_resource.rb +33 -15
- data/lib/cancan/exceptions.rb +3 -0
- data/lib/cancan/model_adapters/abstract_adapter.rb +40 -0
- data/lib/cancan/model_adapters/active_record_adapter.rb +119 -0
- data/lib/cancan/model_adapters/data_mapper_adapter.rb +33 -0
- data/lib/cancan/model_adapters/default_adapter.rb +7 -0
- data/lib/cancan/model_adapters/mongoid_adapter.rb +41 -0
- data/lib/cancan/{active_record_additions.rb → model_additions.rb} +5 -16
- data/lib/cancan/{can_definition.rb → rule.rb} +29 -25
- data/lib/generators/cancan/ability/USAGE +4 -0
- data/lib/generators/cancan/ability/ability_generator.rb +11 -0
- data/lib/generators/cancan/ability/templates/ability.rb +28 -0
- data/spec/README.rdoc +28 -0
- data/spec/cancan/ability_spec.rb +11 -3
- data/spec/cancan/controller_additions_spec.rb +30 -0
- data/spec/cancan/controller_resource_spec.rb +68 -2
- data/spec/cancan/inherited_resource_spec.rb +3 -1
- data/spec/cancan/model_adapters/active_record_adapter_spec.rb +185 -0
- data/spec/cancan/model_adapters/data_mapper_adapter_spec.rb +115 -0
- data/spec/cancan/model_adapters/default_adapter_spec.rb +7 -0
- data/spec/cancan/model_adapters/mongoid_adapter_spec.rb +168 -0
- data/spec/cancan/rule_spec.rb +39 -0
- data/spec/spec_helper.rb +2 -24
- metadata +26 -17
- data/lib/cancan/query.rb +0 -97
- data/spec/cancan/active_record_additions_spec.rb +0 -75
- data/spec/cancan/can_definition_spec.rb +0 -57
- data/spec/cancan/query_spec.rb +0 -107
@@ -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,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cancan
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
5
|
-
prerelease:
|
4
|
+
hash: -1848230027
|
5
|
+
prerelease: true
|
6
6
|
segments:
|
7
7
|
- 1
|
8
|
-
-
|
9
|
-
-
|
10
|
-
|
8
|
+
- 5
|
9
|
+
- 0
|
10
|
+
- beta1
|
11
|
+
version: 1.5.0.beta1
|
11
12
|
platform: ruby
|
12
13
|
authors:
|
13
14
|
- Ryan Bates
|
@@ -15,7 +16,7 @@ autorequire:
|
|
15
16
|
bindir: bin
|
16
17
|
cert_chain: []
|
17
18
|
|
18
|
-
date:
|
19
|
+
date: 2011-01-08 00:00:00 -08:00
|
19
20
|
default_executable:
|
20
21
|
dependencies:
|
21
22
|
- !ruby/object:Gem::Dependency
|
@@ -26,14 +27,12 @@ dependencies:
|
|
26
27
|
requirements:
|
27
28
|
- - ~>
|
28
29
|
- !ruby/object:Gem::Version
|
29
|
-
hash:
|
30
|
+
hash: 11
|
30
31
|
segments:
|
31
32
|
- 2
|
33
|
+
- 1
|
32
34
|
- 0
|
33
|
-
|
34
|
-
- beta
|
35
|
-
- 22
|
36
|
-
version: 2.0.0.beta.22
|
35
|
+
version: 2.1.0
|
37
36
|
type: :development
|
38
37
|
version_requirements: *id001
|
39
38
|
- !ruby/object:Gem::Dependency
|
@@ -94,25 +93,35 @@ extra_rdoc_files: []
|
|
94
93
|
|
95
94
|
files:
|
96
95
|
- lib/cancan/ability.rb
|
97
|
-
- lib/cancan/active_record_additions.rb
|
98
|
-
- lib/cancan/can_definition.rb
|
99
96
|
- lib/cancan/controller_additions.rb
|
100
97
|
- lib/cancan/controller_resource.rb
|
101
98
|
- lib/cancan/exceptions.rb
|
102
99
|
- lib/cancan/inherited_resource.rb
|
103
100
|
- lib/cancan/matchers.rb
|
104
|
-
- lib/cancan/
|
101
|
+
- lib/cancan/model_adapters/abstract_adapter.rb
|
102
|
+
- lib/cancan/model_adapters/active_record_adapter.rb
|
103
|
+
- lib/cancan/model_adapters/data_mapper_adapter.rb
|
104
|
+
- lib/cancan/model_adapters/default_adapter.rb
|
105
|
+
- lib/cancan/model_adapters/mongoid_adapter.rb
|
106
|
+
- lib/cancan/model_additions.rb
|
107
|
+
- lib/cancan/rule.rb
|
105
108
|
- lib/cancan.rb
|
109
|
+
- lib/generators/cancan/ability/ability_generator.rb
|
110
|
+
- lib/generators/cancan/ability/templates/ability.rb
|
111
|
+
- lib/generators/cancan/ability/USAGE
|
106
112
|
- spec/cancan/ability_spec.rb
|
107
|
-
- spec/cancan/active_record_additions_spec.rb
|
108
|
-
- spec/cancan/can_definition_spec.rb
|
109
113
|
- spec/cancan/controller_additions_spec.rb
|
110
114
|
- spec/cancan/controller_resource_spec.rb
|
111
115
|
- spec/cancan/exceptions_spec.rb
|
112
116
|
- spec/cancan/inherited_resource_spec.rb
|
113
117
|
- spec/cancan/matchers_spec.rb
|
114
|
-
- spec/cancan/
|
118
|
+
- spec/cancan/model_adapters/active_record_adapter_spec.rb
|
119
|
+
- spec/cancan/model_adapters/data_mapper_adapter_spec.rb
|
120
|
+
- spec/cancan/model_adapters/default_adapter_spec.rb
|
121
|
+
- spec/cancan/model_adapters/mongoid_adapter_spec.rb
|
122
|
+
- spec/cancan/rule_spec.rb
|
115
123
|
- spec/matchers.rb
|
124
|
+
- spec/README.rdoc
|
116
125
|
- spec/spec.opts
|
117
126
|
- spec/spec_helper.rb
|
118
127
|
- 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
|