cancan 1.4.1 → 1.5.0.beta1
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.
- 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
|