cancancan 1.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. checksums.yaml +15 -0
  2. data/CHANGELOG.rdoc +427 -0
  3. data/CONTRIBUTING.md +11 -0
  4. data/Gemfile +23 -0
  5. data/LICENSE +20 -0
  6. data/README.rdoc +161 -0
  7. data/Rakefile +18 -0
  8. data/init.rb +1 -0
  9. data/lib/cancan.rb +13 -0
  10. data/lib/cancan/ability.rb +324 -0
  11. data/lib/cancan/controller_additions.rb +397 -0
  12. data/lib/cancan/controller_resource.rb +286 -0
  13. data/lib/cancan/exceptions.rb +50 -0
  14. data/lib/cancan/inherited_resource.rb +20 -0
  15. data/lib/cancan/matchers.rb +14 -0
  16. data/lib/cancan/model_adapters/abstract_adapter.rb +56 -0
  17. data/lib/cancan/model_adapters/active_record_adapter.rb +180 -0
  18. data/lib/cancan/model_adapters/data_mapper_adapter.rb +34 -0
  19. data/lib/cancan/model_adapters/default_adapter.rb +7 -0
  20. data/lib/cancan/model_adapters/mongoid_adapter.rb +54 -0
  21. data/lib/cancan/model_additions.rb +31 -0
  22. data/lib/cancan/rule.rb +147 -0
  23. data/lib/cancancan.rb +1 -0
  24. data/lib/generators/cancan/ability/USAGE +4 -0
  25. data/lib/generators/cancan/ability/ability_generator.rb +11 -0
  26. data/lib/generators/cancan/ability/templates/ability.rb +32 -0
  27. data/spec/README.rdoc +28 -0
  28. data/spec/cancan/ability_spec.rb +455 -0
  29. data/spec/cancan/controller_additions_spec.rb +141 -0
  30. data/spec/cancan/controller_resource_spec.rb +553 -0
  31. data/spec/cancan/exceptions_spec.rb +58 -0
  32. data/spec/cancan/inherited_resource_spec.rb +60 -0
  33. data/spec/cancan/matchers_spec.rb +29 -0
  34. data/spec/cancan/model_adapters/active_record_adapter_spec.rb +358 -0
  35. data/spec/cancan/model_adapters/data_mapper_adapter_spec.rb +118 -0
  36. data/spec/cancan/model_adapters/default_adapter_spec.rb +7 -0
  37. data/spec/cancan/model_adapters/mongoid_adapter_spec.rb +226 -0
  38. data/spec/cancan/rule_spec.rb +52 -0
  39. data/spec/matchers.rb +13 -0
  40. data/spec/spec.opts +2 -0
  41. data/spec/spec_helper.rb +77 -0
  42. metadata +126 -0
@@ -0,0 +1,58 @@
1
+ require "spec_helper"
2
+
3
+ describe CanCan::AccessDenied do
4
+ describe "with action and subject" do
5
+ before(:each) do
6
+ @exception = CanCan::AccessDenied.new(nil, :some_action, :some_subject)
7
+ end
8
+
9
+ it "has action and subject accessors" do
10
+ expect(@exception.action).to eq(:some_action)
11
+ expect(@exception.subject).to eq(:some_subject)
12
+ end
13
+
14
+ it "has a changable default message" do
15
+ expect(@exception.message).to eq("You are not authorized to access this page.")
16
+ @exception.default_message = "Unauthorized!"
17
+ expect(@exception.message).to eq("Unauthorized!")
18
+ end
19
+ end
20
+
21
+ describe "with only a message" do
22
+ before(:each) do
23
+ @exception = CanCan::AccessDenied.new("Access denied!")
24
+ end
25
+
26
+ it "has nil action and subject" do
27
+ expect(@exception.action).to be_nil
28
+ expect(@exception.subject).to be_nil
29
+ end
30
+
31
+ it "has passed message" do
32
+ expect(@exception.message).to eq("Access denied!")
33
+ end
34
+ end
35
+
36
+ describe "i18n in the default message" do
37
+ after(:each) do
38
+ I18n.backend = nil
39
+ end
40
+
41
+ it "uses i18n for the default message" do
42
+ I18n.backend.store_translations :en, :unauthorized => {:default => "This is a different message"}
43
+ @exception = CanCan::AccessDenied.new
44
+ expect(@exception.message).to eq("This is a different message")
45
+ end
46
+
47
+ it "defaults to a nice message" do
48
+ @exception = CanCan::AccessDenied.new
49
+ expect(@exception.message).to eq("You are not authorized to access this page.")
50
+ end
51
+
52
+ it "does not use translation if a message is given" do
53
+ @exception = CanCan::AccessDenied.new("Hey! You're not welcome here")
54
+ expect(@exception.message).to eq("Hey! You're not welcome here")
55
+ expect(@exception.message).to_not eq("You are not authorized to access this page.")
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,60 @@
1
+ require "spec_helper"
2
+
3
+ describe CanCan::InheritedResource 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
+ allow(@controller).to receive(:params).and_return { @params }
10
+ allow(@controller).to receive(:current_ability) { @ability }
11
+ allow(@controller_class).to receive(:cancan_skipper) { {:authorize => {}, :load => {}} }
12
+ end
13
+
14
+ it "show loads resource through @controller.resource" do
15
+ @params.merge!(:action => "show", :id => 123)
16
+ allow(@controller).to receive(:resource) { :project_resource }
17
+ CanCan::InheritedResource.new(@controller).load_resource
18
+ expect(@controller.instance_variable_get(:@project)).to eq(:project_resource)
19
+ end
20
+
21
+ it "new loads through @controller.build_resource" do
22
+ @params[:action] = "new"
23
+ allow(@controller).to receive(:build_resource) { :project_resource }
24
+ CanCan::InheritedResource.new(@controller).load_resource
25
+ expect(@controller.instance_variable_get(:@project)).to eq(:project_resource)
26
+ end
27
+
28
+ it "index loads through @controller.association_chain when parent" do
29
+ @params[:action] = "index"
30
+ allow(@controller).to receive(:association_chain) { @controller.instance_variable_set(:@project, :project_resource) }
31
+ CanCan::InheritedResource.new(@controller, :parent => true).load_resource
32
+ expect(@controller.instance_variable_get(:@project)).to eq(:project_resource)
33
+ end
34
+
35
+ it "index loads through @controller.end_of_association_chain" do
36
+ @params[:action] = "index"
37
+ allow(Project).to receive(:accessible_by).with(@ability, :index) { :projects }
38
+ allow(@controller).to receive(:end_of_association_chain) { Project }
39
+ CanCan::InheritedResource.new(@controller).load_resource
40
+ expect(@controller.instance_variable_get(:@projects)).to eq(:projects)
41
+ end
42
+
43
+ it "builds a new resource with attributes from current ability" do
44
+ @params[:action] = "new"
45
+ @ability.can(:create, Project, :name => "from conditions")
46
+ allow(@controller).to receive(:build_resource) { Struct.new(:name).new }
47
+ resource = CanCan::InheritedResource.new(@controller)
48
+ resource.load_resource
49
+ expect(@controller.instance_variable_get(:@project).name).to eq("from conditions")
50
+ end
51
+
52
+ it "overrides initial attributes with params" do
53
+ @params.merge!(:action => "new", :project => {:name => "from params"})
54
+ @ability.can(:create, Project, :name => "from conditions")
55
+ allow(@controller).to receive(:build_resource) { Struct.new(:name).new }
56
+ resource = CanCan::ControllerResource.new(@controller)
57
+ resource.load_resource
58
+ expect(@controller.instance_variable_get(:@project).name).to eq("from params")
59
+ end
60
+ end
@@ -0,0 +1,29 @@
1
+ require "spec_helper"
2
+
3
+ describe "be_able_to" do
4
+ it "delegates to can?" do
5
+ expect(object = double).to receive(:can?).with(:read, 123) { true }
6
+ expect(object).to be_able_to(:read, 123)
7
+ end
8
+
9
+ it "reports a nice failure message for should" do
10
+ expect(object = double).to receive(:can?).with(:read, 123) { false }
11
+ expect {
12
+ expect(object).to be_able_to(:read, 123)
13
+ }.to raise_error('expected to be able to :read 123')
14
+ end
15
+
16
+ it "reports a nice failure message for should not" do
17
+ expect(object = double).to receive(:can?).with(:read, 123) { true }
18
+ expect {
19
+ expect(object).to_not be_able_to(:read, 123)
20
+ }.to raise_error('expected not to be able to :read 123')
21
+ end
22
+
23
+ it "delegates additional arguments to can? and reports in failure message" do
24
+ expect(object = double).to receive(:can?).with(:read, 123, 456) { false }
25
+ expect {
26
+ expect(object).to be_able_to(:read, 123, 456)
27
+ }.to raise_error('expected to be able to :read 123 456')
28
+ end
29
+ end
@@ -0,0 +1,358 @@
1
+ if ENV["MODEL_ADAPTER"].nil? || ENV["MODEL_ADAPTER"] == "active_record"
2
+ require "spec_helper"
3
+
4
+ ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :database => ":memory:")
5
+
6
+ describe CanCan::ModelAdapters::ActiveRecordAdapter do
7
+ with_model :category do
8
+ table do |t|
9
+ t.string "name"
10
+ t.boolean "visible"
11
+ end
12
+ model do
13
+ has_many :articles
14
+ end
15
+ end
16
+
17
+ with_model :article do
18
+ table do |t|
19
+ t.string "name"
20
+ t.boolean "published"
21
+ t.boolean "secret"
22
+ t.integer "priority"
23
+ t.integer "category_id"
24
+ t.integer "user_id"
25
+ end
26
+ model do
27
+ belongs_to :category
28
+ has_many :comments
29
+ belongs_to :user
30
+ end
31
+ end
32
+
33
+ with_model :comment do
34
+ table do |t|
35
+ t.boolean "spam"
36
+ t.integer "article_id"
37
+ end
38
+ model do
39
+ belongs_to :article
40
+ end
41
+ end
42
+
43
+ with_model :user do
44
+ table do |t|
45
+
46
+ end
47
+ model do
48
+ has_many :articles
49
+ end
50
+ end
51
+
52
+ before(:each) do
53
+ Article.delete_all
54
+ Comment.delete_all
55
+ (@ability = double).extend(CanCan::Ability)
56
+ @article_table = Article.table_name
57
+ @comment_table = Comment.table_name
58
+ end
59
+
60
+ it "is for only active record classes" do
61
+ expect(CanCan::ModelAdapters::ActiveRecordAdapter).to_not be_for_class(Object)
62
+ expect(CanCan::ModelAdapters::ActiveRecordAdapter).to be_for_class(Article)
63
+ expect(CanCan::ModelAdapters::AbstractAdapter.adapter_class(Article)).to eq(CanCan::ModelAdapters::ActiveRecordAdapter)
64
+ end
65
+
66
+ it "finds record" do
67
+ article = Article.create!
68
+ expect(CanCan::ModelAdapters::ActiveRecordAdapter.find(Article, article.id)).to eq(article)
69
+ end
70
+
71
+ it "does not fetch any records when no abilities are defined" do
72
+ Article.create!
73
+ expect(Article.accessible_by(@ability)).to be_empty
74
+ end
75
+
76
+ it "fetches all articles when one can read all" do
77
+ @ability.can :read, Article
78
+ article = Article.create!
79
+ expect(Article.accessible_by(@ability)).to eq([article])
80
+ end
81
+
82
+ it "fetches only the articles that are published" do
83
+ @ability.can :read, Article, :published => true
84
+ article1 = Article.create!(:published => true)
85
+ article2 = Article.create!(:published => false)
86
+ expect(Article.accessible_by(@ability)).to eq([article1])
87
+ end
88
+
89
+ it "fetches any articles which are published or secret" do
90
+ @ability.can :read, Article, :published => true
91
+ @ability.can :read, Article, :secret => true
92
+ article1 = Article.create!(:published => true, :secret => false)
93
+ article2 = Article.create!(:published => true, :secret => true)
94
+ article3 = Article.create!(:published => false, :secret => true)
95
+ article4 = Article.create!(:published => false, :secret => false)
96
+ expect(Article.accessible_by(@ability)).to eq([article1, article2, article3])
97
+ end
98
+
99
+ it "fetches only the articles that are published and not secret" do
100
+ @ability.can :read, Article, :published => true
101
+ @ability.cannot :read, Article, :secret => true
102
+ article1 = Article.create!(:published => true, :secret => false)
103
+ article2 = Article.create!(:published => true, :secret => true)
104
+ article3 = Article.create!(:published => false, :secret => true)
105
+ article4 = Article.create!(:published => false, :secret => false)
106
+ expect(Article.accessible_by(@ability)).to eq([article1])
107
+ end
108
+
109
+ it "only reads comments for articles which are published" do
110
+ @ability.can :read, Comment, :article => { :published => true }
111
+ comment1 = Comment.create!(:article => Article.create!(:published => true))
112
+ comment2 = Comment.create!(:article => Article.create!(:published => false))
113
+ expect(Comment.accessible_by(@ability)).to eq([comment1])
114
+ end
115
+
116
+ it "should only read articles which are published or in visible categories" do
117
+ @ability.can :read, Article, :category => { :visible => true }
118
+ @ability.can :read, Article, :published => true
119
+ article1 = Article.create!(:published => true)
120
+ article2 = Article.create!(:published => false)
121
+ article3 = Article.create!(:published => false, :category => Category.create!(:visible => true))
122
+ expect(Article.accessible_by(@ability)).to eq([article1, article3])
123
+ end
124
+
125
+ it "should only read categories once even if they have multiple articles" do
126
+ @ability.can :read, Category, :articles => { :published => true }
127
+ @ability.can :read, Article, :published => true
128
+ category = Category.create!
129
+ Article.create!(:published => true, :category => category)
130
+ Article.create!(:published => true, :category => category)
131
+ expect(Category.accessible_by(@ability)).to eq([category])
132
+ end
133
+
134
+ it "only reads comments for visible categories through articles" do
135
+ @ability.can :read, Comment, :article => { :category => { :visible => true } }
136
+ comment1 = Comment.create!(:article => Article.create!(:category => Category.create!(:visible => true)))
137
+ comment2 = Comment.create!(:article => Article.create!(:category => Category.create!(:visible => false)))
138
+ expect(Comment.accessible_by(@ability)).to eq([comment1])
139
+ end
140
+
141
+ it "allows conditions in SQL and merge with hash conditions" do
142
+ @ability.can :read, Article, :published => true
143
+ @ability.can :read, Article, ["secret=?", true]
144
+ article1 = Article.create!(:published => true, :secret => false)
145
+ article2 = Article.create!(:published => true, :secret => true)
146
+ article3 = Article.create!(:published => false, :secret => true)
147
+ article4 = Article.create!(:published => false, :secret => false)
148
+ expect(Article.accessible_by(@ability)).to eq([article1, article2, article3])
149
+ end
150
+
151
+ it "allows a scope for conditions" do
152
+ @ability.can :read, Article, Article.where(:secret => true)
153
+ article1 = Article.create!(:secret => true)
154
+ article2 = Article.create!(:secret => false)
155
+ expect(Article.accessible_by(@ability)).to eq([article1])
156
+ end
157
+
158
+ it "fetches only associated records when using with a scope for conditions" do
159
+ @ability.can :read, Article, Article.where(:secret => true)
160
+ category1 = Category.create!(:visible => false)
161
+ category2 = Category.create!(:visible => true)
162
+ article1 = Article.create!(:secret => true, :category => category1)
163
+ article2 = Article.create!(:secret => true, :category => category2)
164
+ expect(category1.articles.accessible_by(@ability)).to eq([article1])
165
+ end
166
+
167
+ it "raises an exception when trying to merge scope with other conditions" do
168
+ @ability.can :read, Article, :published => true
169
+ @ability.can :read, Article, Article.where(:secret => true)
170
+ expect(lambda { Article.accessible_by(@ability) }).to raise_error(CanCan::Error, "Unable to merge an Active Record scope with other conditions. Instead use a hash or SQL for read Article ability.")
171
+ end
172
+
173
+ it "does not allow to fetch records when ability with just block present" do
174
+ @ability.can :read, Article do
175
+ false
176
+ end
177
+ expect(lambda { Article.accessible_by(@ability) }).to raise_error(CanCan::Error)
178
+ end
179
+
180
+ it "should support more than one deeply nested conditions" do
181
+ @ability.can :read, Comment, :article => {
182
+ :category => {
183
+ :name => 'foo', :visible => true
184
+ }
185
+ }
186
+ expect { Comment.accessible_by(@ability) }.to_not raise_error
187
+ end
188
+
189
+ it "does not allow to check ability on object against SQL conditions without block" do
190
+ @ability.can :read, Article, ["secret=?", true]
191
+ expect(lambda { @ability.can? :read, Article.new }).to raise_error(CanCan::Error)
192
+ end
193
+
194
+ it "has false conditions if no abilities match" do
195
+ expect(@ability.model_adapter(Article, :read).conditions).to eq("'t'='f'")
196
+ end
197
+
198
+ it "returns false conditions for cannot clause" do
199
+ @ability.cannot :read, Article
200
+ expect(@ability.model_adapter(Article, :read).conditions).to eq("'t'='f'")
201
+ end
202
+
203
+ it "returns SQL for single `can` definition in front of default `cannot` condition" do
204
+ @ability.cannot :read, Article
205
+ @ability.can :read, Article, :published => false, :secret => true
206
+ expect(@ability.model_adapter(Article, :read).conditions).to orderlessly_match(%Q["#{@article_table}"."published" = 'f' AND "#{@article_table}"."secret" = 't'])
207
+ end
208
+
209
+ it "returns true condition for single `can` definition in front of default `can` condition" do
210
+ @ability.can :read, Article
211
+ @ability.can :read, Article, :published => false, :secret => true
212
+ expect(@ability.model_adapter(Article, :read).conditions).to eq("'t'='t'")
213
+ end
214
+
215
+ it "returns `false condition` for single `cannot` definition in front of default `cannot` condition" do
216
+ @ability.cannot :read, Article
217
+ @ability.cannot :read, Article, :published => false, :secret => true
218
+ expect(@ability.model_adapter(Article, :read).conditions).to eq("'t'='f'")
219
+ end
220
+
221
+ it "returns `not (sql)` for single `cannot` definition in front of default `can` condition" do
222
+ @ability.can :read, Article
223
+ @ability.cannot :read, Article, :published => false, :secret => true
224
+ expect(@ability.model_adapter(Article, :read).conditions).to orderlessly_match(%Q["not (#{@article_table}"."published" = 'f' AND "#{@article_table}"."secret" = 't')])
225
+ end
226
+
227
+ it "returns appropriate sql conditions in complex case" do
228
+ @ability.can :read, Article
229
+ @ability.can :manage, Article, :id => 1
230
+ @ability.can :update, Article, :published => true
231
+ @ability.cannot :update, Article, :secret => true
232
+ expect(@ability.model_adapter(Article, :update).conditions).to eq(%Q[not ("#{@article_table}"."secret" = 't') AND (("#{@article_table}"."published" = 't') OR ("#{@article_table}"."id" = 1))])
233
+ expect(@ability.model_adapter(Article, :manage).conditions).to eq({:id => 1})
234
+ expect(@ability.model_adapter(Article, :read).conditions).to eq("'t'='t'")
235
+ end
236
+
237
+ it "returns appropriate sql conditions in complex case with nested joins" do
238
+ @ability.can :read, Comment, :article => { :category => { :visible => true } }
239
+ expect(@ability.model_adapter(Comment, :read).conditions).to eq({ Category.table_name.to_sym => { :visible => true } })
240
+ end
241
+
242
+ it "returns appropriate sql conditions in complex case with nested joins of different depth" do
243
+ @ability.can :read, Comment, :article => { :published => true, :category => { :visible => true } }
244
+ expect(@ability.model_adapter(Comment, :read).conditions).to eq({ Article.table_name.to_sym => { :published => true }, Category.table_name.to_sym => { :visible => true } })
245
+ end
246
+
247
+ it "does not forget conditions when calling with SQL string" do
248
+ @ability.can :read, Article, :published => true
249
+ @ability.can :read, Article, ['secret=?', false]
250
+ adapter = @ability.model_adapter(Article, :read)
251
+ 2.times do
252
+ expect(adapter.conditions).to eq(%Q[(secret='f') OR ("#{@article_table}"."published" = 't')])
253
+ end
254
+ end
255
+
256
+ it "has nil joins if no rules" do
257
+ expect(@ability.model_adapter(Article, :read).joins).to be_nil
258
+ end
259
+
260
+ it "has nil joins if no nested hashes specified in conditions" do
261
+ @ability.can :read, Article, :published => false
262
+ @ability.can :read, Article, :secret => true
263
+ expect(@ability.model_adapter(Article, :read).joins).to be_nil
264
+ end
265
+
266
+ it "merges separate joins into a single array" do
267
+ @ability.can :read, Article, :project => { :blocked => false }
268
+ @ability.can :read, Article, :company => { :admin => true }
269
+ expect(@ability.model_adapter(Article, :read).joins.inspect).to orderlessly_match([:company, :project].inspect)
270
+ end
271
+
272
+ it "merges same joins into a single array" do
273
+ @ability.can :read, Article, :project => { :blocked => false }
274
+ @ability.can :read, Article, :project => { :admin => true }
275
+ expect(@ability.model_adapter(Article, :read).joins).to eq([:project])
276
+ end
277
+
278
+ it "merges nested and non-nested joins" do
279
+ @ability.can :read, Article, :project => { :blocked => false }
280
+ @ability.can :read, Article, :project => { :comments => { :spam => true } }
281
+ expect(@ability.model_adapter(Article, :read).joins).to eq([{:project=>[:comments]}])
282
+ end
283
+
284
+ it "merges :all conditions with other conditions" do
285
+ user = User.create!
286
+ article = Article.create!(:user => user)
287
+ ability = Ability.new(user)
288
+ ability.can :manage, :all
289
+ ability.can :manage, Article, :user_id => user.id
290
+ expect(Article.accessible_by(ability)).to eq([article])
291
+ end
292
+
293
+ it "restricts articles given a MetaWhere condition" do
294
+ @ability.can :read, Article, :priority.lt => 2
295
+ article1 = Article.create!(:priority => 1)
296
+ article2 = Article.create!(:priority => 3)
297
+ expect(Article.accessible_by(@ability)).to eq([article1])
298
+ expect(@ability).to be_able_to(:read, article1)
299
+ expect(@ability).to_not be_able_to(:read, article2)
300
+ end
301
+
302
+ it "merges MetaWhere and non-MetaWhere conditions" do
303
+ @ability.can :read, Article, :priority.lt => 2
304
+ @ability.can :read, Article, :priority => 1
305
+ article1 = Article.create!(:priority => 1)
306
+ article2 = Article.create!(:priority => 3)
307
+ expect(Article.accessible_by(@ability)).to eq([article1])
308
+ expect(@ability).to be_able_to(:read, article1)
309
+ expect(@ability).to_not be_able_to(:read, article2)
310
+ end
311
+
312
+ it "matches any MetaWhere condition" do
313
+ adapter = CanCan::ModelAdapters::ActiveRecordAdapter
314
+ article1 = Article.new(:priority => 1, :name => "Hello World")
315
+ expect(adapter.matches_condition?(article1, :priority.eq, 1)).to be_true
316
+ expect(adapter.matches_condition?(article1, :priority.eq, 2)).to be_false
317
+ expect(adapter.matches_condition?(article1, :priority.eq_any, [1, 2])).to be_true
318
+ expect(adapter.matches_condition?(article1, :priority.eq_any, [2, 3])).to be_false
319
+ expect(adapter.matches_condition?(article1, :priority.eq_all, [1, 1])).to be_true
320
+ expect(adapter.matches_condition?(article1, :priority.eq_all, [1, 2])).to be_false
321
+ expect(adapter.matches_condition?(article1, :priority.ne, 2)).to be_true
322
+ expect(adapter.matches_condition?(article1, :priority.ne, 1)).to be_false
323
+ expect(adapter.matches_condition?(article1, :priority.in, [1, 2])).to be_true
324
+ expect(adapter.matches_condition?(article1, :priority.in, [2, 3])).to be_false
325
+ expect(adapter.matches_condition?(article1, :priority.nin, [2, 3])).to be_true
326
+ expect(adapter.matches_condition?(article1, :priority.nin, [1, 2])).to be_false
327
+ expect(adapter.matches_condition?(article1, :priority.lt, 2)).to be_true
328
+ expect(adapter.matches_condition?(article1, :priority.lt, 1)).to be_false
329
+ expect(adapter.matches_condition?(article1, :priority.lteq, 1)).to be_true
330
+ expect(adapter.matches_condition?(article1, :priority.lteq, 0)).to be_false
331
+ expect(adapter.matches_condition?(article1, :priority.gt, 0)).to be_true
332
+ expect(adapter.matches_condition?(article1, :priority.gt, 1)).to be_false
333
+ expect(adapter.matches_condition?(article1, :priority.gteq, 1)).to be_true
334
+ expect(adapter.matches_condition?(article1, :priority.gteq, 2)).to be_false
335
+ expect(adapter.matches_condition?(article1, :name.like, "%ello worl%")).to be_true
336
+ expect(adapter.matches_condition?(article1, :name.like, "hello world")).to be_true
337
+ expect(adapter.matches_condition?(article1, :name.like, "hello%")).to be_true
338
+ expect(adapter.matches_condition?(article1, :name.like, "h%d")).to be_true
339
+ expect(adapter.matches_condition?(article1, :name.like, "%helo%")).to be_false
340
+ expect(adapter.matches_condition?(article1, :name.like, "hello")).to be_false
341
+ expect(adapter.matches_condition?(article1, :name.like, "hello.world")).to be_false
342
+ # For some reason this is reporting "The not_matches MetaWhere condition is not supported."
343
+ # expect(adapter.matches_condition?(article1, :name.nlike, "%helo%")).to be_true
344
+ # expect(adapter.matches_condition?(article1, :name.nlike, "%ello worl%")).to be_false
345
+ end
346
+
347
+ it 'should not execute a scope when checking ability on the class' do
348
+ relation = Article.where(:secret => true)
349
+ @ability.can :read, Article, relation do |article|
350
+ article.secret == true
351
+ end
352
+
353
+ relation.stub(:count).and_raise('Unexpected scope execution.')
354
+
355
+ expect { @ability.can? :read, Article }.not_to raise_error
356
+ end
357
+ end
358
+ end