cantango-core 0.1.2 → 0.1.3
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +7 -1
- data/Gemfile.lock +70 -12
- data/README.mdown +16 -14
- data/VERSION +1 -1
- data/cantango-core.gemspec +41 -51
- data/lib/cantango/ability/base/callbacks.rb +37 -0
- data/lib/cantango/ability/base.rb +21 -8
- data/lib/cantango/ability/cache.rb +1 -1
- data/lib/cantango/ability/executor/modes.rb +6 -6
- data/lib/cantango/ability/executor/no_cache_mode.rb +2 -6
- data/lib/cantango/ability/executor.rb +1 -1
- data/lib/cantango/ability/helper/account.rb +6 -10
- data/lib/cantango/ability/helper/engine.rb +22 -26
- data/lib/cantango/ability/helper/user.rb +10 -14
- data/lib/cantango/ability/helper.rb +1 -1
- data/lib/cantango/ability.rb +7 -2
- data/lib/cantango/adaptor/active_record.rb +6 -0
- data/lib/cantango/adaptor/data_mapper.rb +5 -0
- data/lib/cantango/adaptor/generic.rb +12 -0
- data/lib/cantango/adaptor/mongo.rb +13 -0
- data/lib/cantango/adaptor/mongo_mapper.rb +5 -0
- data/lib/cantango/adaptor/mongoid.rb +5 -0
- data/lib/cantango/adaptor/relational.rb +8 -0
- data/lib/cantango/{rules/adaptor.rb → adaptor.rb} +4 -4
- data/lib/cantango/{rules → cancan}/rule_class.rb +1 -1
- data/lib/cantango/cancan.rb +5 -0
- data/lib/cantango/core.rb +5 -13
- data/lib/cantango/engine.rb +6 -16
- data/lib/cantango/filter/base.rb +1 -1
- data/lib/cantango/helpers/debug.rb +31 -1
- data/lib/cantango/loader/yaml.rb +2 -11
- data/lib/cantango/model/guest.rb +3 -1
- data/spec/cantango/ability/base_spec.rb +13 -63
- data/spec/cantango/ability/cache/simple_key_spec.rb +29 -0
- data/spec/cantango/ability/executor/base_spec.rb +12 -52
- data/spec/cantango/ability/executor/custom_spec.rb +51 -0
- data/spec/cantango/ability/executor/modes_spec.rb +27 -49
- data/spec/cantango/ability/executor/no_cache_mode_spec.rb +29 -0
- data/spec/cantango/ability/helper/account_spec.rb +37 -0
- data/spec/cantango/ability/helper/engine_spec.rb +36 -0
- data/spec/cantango/ability/helper/user_spec.rb +38 -0
- data/spec/cantango/adaptor/active_record_spec.rb +38 -0
- data/spec/cantango/adaptor/data_mapper_spec.rb +39 -0
- data/spec/cantango/{rules/adaptor → adaptor}/mongo_mapper_spec.rb +0 -0
- data/spec/cantango/{rules/adaptor → adaptor}/mongoid_spec.rb +0 -0
- data/spec/cantango/cancan/rule_spec.rb +5 -0
- data/spec/cantango/core_spec.rb +0 -2
- data/spec/cantango/engine_spec.rb +51 -0
- data/spec/cantango/filter/base_spec.rb +25 -0
- data/spec/cantango/helpers/debug_spec.rb +29 -0
- data/spec/cantango/loader/yaml_spec.rb +5 -0
- data/spec/cantango/model/guest_spec.rb +14 -0
- data/spec/cantango/rspec/be_allowed_to_spec.rb +5 -0
- data/spec/cantango/scope/ability_spec.rb +33 -0
- data/spec/fixtures/models/account.rb +7 -0
- data/spec/fixtures/models/admin.rb +2 -0
- data/spec/fixtures/models/admin_account.rb +8 -0
- data/spec/fixtures/models/items.rb +11 -0
- data/spec/fixtures/models/user.rb +20 -0
- data/spec/fixtures/models.rb +2 -0
- data/spec/spec_helper.rb +4 -0
- metadata +60 -67
- data/lib/cantango/ability/executor/cache_mode.rb +0 -33
- data/lib/cantango/ability/helper/role.rb +0 -21
- data/lib/cantango/ability/helper/role_group.rb +0 -21
- data/lib/cantango/macros/account.rb +0 -14
- data/lib/cantango/macros/user.rb +0 -16
- data/lib/cantango/macros.rb +0 -11
- data/lib/cantango/rules/adaptor/active_record.rb +0 -10
- data/lib/cantango/rules/adaptor/data_mapper.rb +0 -11
- data/lib/cantango/rules/adaptor/generic.rb +0 -16
- data/lib/cantango/rules/adaptor/mongo.rb +0 -19
- data/lib/cantango/rules/adaptor/mongo_mapper.rb +0 -10
- data/lib/cantango/rules/adaptor/mongoid.rb +0 -9
- data/lib/cantango/rules/adaptor/relational.rb +0 -13
- data/lib/cantango/rules/dsl.rb +0 -24
- data/lib/cantango/rules/relation.rb +0 -67
- data/lib/cantango/rules/scope.rb +0 -24
- data/lib/cantango/rules.rb +0 -8
- data/spec/cantango/ability/cached_spec.rb +0 -0
- data/spec/cantango/ability/executor/base2.rb +0 -75
- data/spec/cantango/ability/executor/cache_mode_spec.rb +0 -77
- data/spec/cantango/macros/account_spec.rb +0 -0
- data/spec/cantango/macros/user_spec.rb +0 -0
- data/spec/cantango/rules/adaptor/active_record_spec.rb +0 -0
- data/spec/cantango/rules/adaptor/data_mapper_spec.rb +0 -0
- data/spec/cantango/rules/adaptor_spec.rb +0 -0
- data/spec/cantango/rules/dsl_spec.rb +0 -0
- data/spec/cantango/rules/relation_spec.rb +0 -0
- data/spec/cantango/rules/rule_class_spec.rb +0 -0
- data/spec/cantango/rules/scope_spec.rb +0 -0
- data/spec/cantango/rules_spec.rb +0 -55
@@ -1,32 +1,28 @@
|
|
1
|
-
module CanTango
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
end
|
10
|
-
end
|
1
|
+
module CanTango::Ability::Helper
|
2
|
+
module Engine
|
3
|
+
def execute_engines!
|
4
|
+
each_engine do |engine|
|
5
|
+
engine_rules = engine.new(self).execute! if engine
|
6
|
+
@rules << engine_rules if !engine_rules.blank?
|
7
|
+
end
|
8
|
+
end
|
11
9
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
10
|
+
def each_engine &block
|
11
|
+
engines.execution_order.each do |name|
|
12
|
+
yield engines.registered[name] if engines.active? name
|
13
|
+
end
|
14
|
+
end
|
17
15
|
|
18
|
-
|
19
|
-
|
20
|
-
|
16
|
+
def opts_engines_off?
|
17
|
+
options[:engines] == :off
|
18
|
+
end
|
21
19
|
|
22
|
-
|
23
|
-
|
24
|
-
|
20
|
+
def engines_on?
|
21
|
+
CanTango.config.engines.any?(:on) && !opts_engines_off?
|
22
|
+
end
|
25
23
|
|
26
|
-
|
27
|
-
|
28
|
-
end
|
29
|
-
end
|
24
|
+
def engines
|
25
|
+
CanTango.config.engines
|
30
26
|
end
|
31
27
|
end
|
32
|
-
end
|
28
|
+
end
|
@@ -1,18 +1,14 @@
|
|
1
|
-
module CanTango
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
subject
|
8
|
-
end
|
1
|
+
module CanTango::Ability::Helper
|
2
|
+
module User
|
3
|
+
def user
|
4
|
+
return subject.user if subject.respond_to? :user
|
5
|
+
subject
|
6
|
+
end
|
9
7
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
end
|
15
|
-
end
|
8
|
+
def user_key_field
|
9
|
+
key_field = CanTango.config.user.unique_key_field
|
10
|
+
raise "\nModel <#{user.class}> has no ##{key_field} as defined in CanTango.config.user.unique_key_field" if !user.respond_to?(key_field)
|
11
|
+
key_field
|
16
12
|
end
|
17
13
|
end
|
18
14
|
end
|
data/lib/cantango/ability.rb
CHANGED
@@ -0,0 +1,12 @@
|
|
1
|
+
module CanTango::Adaptor
|
2
|
+
module Generic
|
3
|
+
|
4
|
+
def attribute_condition attribute, candidate
|
5
|
+
Proc.new { |model| model.send(attribute) == candidate }
|
6
|
+
end
|
7
|
+
|
8
|
+
def include_condition attribute, candidate
|
9
|
+
Proc.new { |model| model.send(attribute).include? candidate }
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module CanTango::Adaptor
|
2
|
+
module Mongo
|
3
|
+
#include CanTango::Rules::Adaptor::Generic
|
4
|
+
# using #in on Hash (Mongoid query)
|
5
|
+
def include_condition attribute, candidate
|
6
|
+
{ attribute.to_sym.in => candidate.send(attribute) }
|
7
|
+
end
|
8
|
+
|
9
|
+
def attribute_condition attribute, user_scope
|
10
|
+
{ attribute.to_sym => candidate.send(attribute) }
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -25,10 +25,10 @@ module CanTango
|
|
25
25
|
|
26
26
|
def orm_map
|
27
27
|
{
|
28
|
-
:active_record
|
29
|
-
:data_mapper
|
30
|
-
:mongoid
|
31
|
-
:mongo_mapper
|
28
|
+
:active_record => "ActiveRecord::Base",
|
29
|
+
:data_mapper => "DataMapper::Resource",
|
30
|
+
:mongoid => "Mongoid::Document",
|
31
|
+
:mongo_mapper => "MongoMapper::Document"
|
32
32
|
}
|
33
33
|
end
|
34
34
|
end
|
data/lib/cantango/core.rb
CHANGED
@@ -1,10 +1,3 @@
|
|
1
|
-
require 'cantango/rails/railtie' if defined?(Rails)
|
2
|
-
require 'cantango/rails/engine' if defined?(Rails)
|
3
|
-
|
4
|
-
# essential cantango extensions
|
5
|
-
# require 'cantango/config'
|
6
|
-
# require 'cantango/api'
|
7
|
-
|
8
1
|
require 'cancan'
|
9
2
|
require 'active_support' # for Delegate module
|
10
3
|
require 'active_support/core_ext/module/delegation'
|
@@ -15,12 +8,11 @@ require 'sugar-high/blank'
|
|
15
8
|
require 'hashie'
|
16
9
|
require 'sweetloader'
|
17
10
|
|
18
|
-
|
11
|
+
SweetLoader.namespaces = {:CanTango => 'cantango'}
|
12
|
+
SweetLoader.mode = :require
|
19
13
|
|
20
14
|
module CanTango
|
21
|
-
autoload_modules :Ability, :Engine, :Filter
|
22
|
-
autoload_modules :
|
23
|
-
autoload_modules :
|
15
|
+
autoload_modules :Helpers, :Ability, :Engine, :Filter
|
16
|
+
autoload_modules :Loader, :Model
|
17
|
+
autoload_modules :Scope
|
24
18
|
end
|
25
|
-
|
26
|
-
require 'cantango/macros'
|
data/lib/cantango/engine.rb
CHANGED
@@ -2,12 +2,12 @@ module CanTango
|
|
2
2
|
class Engine
|
3
3
|
include CanTango::Helpers::Debug
|
4
4
|
|
5
|
-
attr_reader :ability
|
5
|
+
attr_reader :ability, :options
|
6
6
|
|
7
7
|
delegate :session, :user, :subject, :candidate, :cached?, :to => :ability
|
8
8
|
|
9
|
-
def initialize ability
|
10
|
-
@ability = ability
|
9
|
+
def initialize ability, options = {}
|
10
|
+
@ability, @options = [ability, options]
|
11
11
|
end
|
12
12
|
|
13
13
|
def execute!
|
@@ -18,22 +18,12 @@ module CanTango
|
|
18
18
|
raise NotImplementedError
|
19
19
|
end
|
20
20
|
|
21
|
-
|
22
|
-
|
23
|
-
def valid_mode?
|
24
|
-
valid_cache_mode? || valid_no_cache_mode?
|
25
|
-
end
|
26
|
-
|
27
|
-
def valid_cache_mode?
|
28
|
-
modes.include?(:cache) && cached?
|
29
|
-
end
|
30
|
-
|
31
|
-
def valid_no_cache_mode?
|
32
|
-
modes.include?(:no_cache) && !cached?
|
21
|
+
def valid_mode? mode
|
22
|
+
modes.include? mode.to_sym
|
33
23
|
end
|
34
24
|
|
35
25
|
def modes
|
36
|
-
|
26
|
+
@modes ||= options[:modes] || []
|
37
27
|
end
|
38
28
|
end
|
39
29
|
end
|
data/lib/cantango/filter/base.rb
CHANGED
@@ -1,9 +1,39 @@
|
|
1
1
|
module CanTango
|
2
2
|
module Helpers
|
3
3
|
module Debug
|
4
|
+
attr_writer :do_debug, :debug_writer
|
5
|
+
|
6
|
+
def self.included base
|
7
|
+
base.extend ClassMethods
|
8
|
+
end
|
9
|
+
|
10
|
+
module ClassMethods
|
11
|
+
attr_writer :do_debug, :debug_writer
|
12
|
+
|
13
|
+
def debug?
|
14
|
+
@do_debug ||= false
|
15
|
+
end
|
16
|
+
|
17
|
+
def debug_writer
|
18
|
+
@debug_writer ||= lambda {|m| puts m }
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
4
22
|
# you can set another writer on CanTango.config.debug, fx to spec it!
|
5
23
|
def debug msg
|
6
|
-
|
24
|
+
if debug?
|
25
|
+
return debug_writer.write msg if debug_writer.respond_to? :write
|
26
|
+
return debug_writer.call(msg) if debug_writer.respond_to? :call
|
27
|
+
raise "No debug_writer set!"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def debug?
|
32
|
+
@do_debug ||= self.class.debug?
|
33
|
+
end
|
34
|
+
|
35
|
+
def debug_writer
|
36
|
+
@debug_writer ||= self.class.debug_writer
|
7
37
|
end
|
8
38
|
end
|
9
39
|
end
|
data/lib/cantango/loader/yaml.rb
CHANGED
@@ -14,19 +14,10 @@ module CanTango
|
|
14
14
|
def yml_content
|
15
15
|
YAML.load_file(file_name)
|
16
16
|
rescue
|
17
|
-
raise "Couldn't
|
17
|
+
raise "Couldn't YAML file: #{file_name}"
|
18
18
|
end
|
19
|
-
|
19
|
+
|
20
20
|
module ClassMethods
|
21
|
-
protected
|
22
|
-
|
23
|
-
def config_file name
|
24
|
-
File.join(config_path, "#{name}.yml") if rails?
|
25
|
-
end
|
26
|
-
|
27
|
-
def config_path
|
28
|
-
CanTango.config.permissions.config_path
|
29
|
-
end
|
30
21
|
end
|
31
22
|
end
|
32
23
|
end
|
data/lib/cantango/model/guest.rb
CHANGED
@@ -5,12 +5,14 @@ module CanTango
|
|
5
5
|
module Guest
|
6
6
|
def self.included(base)
|
7
7
|
base.extend ::ActiveModel::Naming
|
8
|
+
base.extend ::ActiveModel::Callbacks
|
9
|
+
|
8
10
|
base.send :include, ::ActiveModel::Conversion
|
9
11
|
base.send :include, ::ActiveModel::Validations
|
10
12
|
end
|
11
13
|
|
12
14
|
def email
|
13
|
-
'guest@
|
15
|
+
'guest@example.com'
|
14
16
|
end
|
15
17
|
|
16
18
|
def has_role? role
|
@@ -1,73 +1,23 @@
|
|
1
|
-
require '
|
2
|
-
require 'cantango'
|
1
|
+
require 'spec_helper'
|
3
2
|
require 'fixtures/models'
|
4
|
-
require 'cantango/rspec'
|
5
3
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
config.engines.all :on
|
14
|
-
|
15
|
-
config.permission_engine.config_path = config_folder
|
16
|
-
config.categories.register :blog_items => [Article, Post]
|
17
|
-
end
|
18
|
-
|
19
|
-
class PublishersRoleGroupPermit < CanTango::RoleGroupPermit
|
20
|
-
def initialize ability
|
21
|
-
super
|
22
|
-
end
|
23
|
-
|
24
|
-
protected
|
25
|
-
|
26
|
-
def static_rules
|
27
|
-
can :write, category(:blog_items)
|
28
|
-
cannot :write, Post
|
4
|
+
module CanTango::Ability
|
5
|
+
class Base
|
6
|
+
include CanTango::Ability::Helper::Account
|
7
|
+
|
8
|
+
def permit_rules
|
9
|
+
can :edit, Project
|
10
|
+
end
|
29
11
|
end
|
30
12
|
end
|
31
13
|
|
32
|
-
|
33
|
-
def initialize ability
|
34
|
-
super
|
35
|
-
end
|
36
|
-
|
37
|
-
protected
|
38
|
-
|
39
|
-
def static_rules
|
40
|
-
can :read, Comment
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
|
45
|
-
describe CanTango::Ability do
|
46
|
-
let (:user) do
|
47
|
-
User.new 'krisy', 'krisy@gmail.com'
|
48
|
-
end
|
49
|
-
|
50
|
-
let (:user_account) do
|
51
|
-
ua = UserAccount.new user, :roles => [:editor], :role_groups => [:publishers]
|
52
|
-
user.account = ua
|
53
|
-
end
|
54
|
-
|
14
|
+
describe CanTango::Ability::Base do
|
55
15
|
before do
|
56
|
-
|
57
|
-
@
|
16
|
+
user = User.new 'krisy', 'krisy@gmail.com'
|
17
|
+
@account = Account.new user
|
58
18
|
end
|
59
19
|
|
60
|
-
|
61
|
-
specify { CanTango.config.role_groups.excluded.should be_empty }
|
62
|
-
|
63
|
-
subject { @ability }
|
64
|
-
specify { @ability.should be_allowed_to(:read, Comment) }
|
65
|
-
specify { @ability.should be_allowed_to(:write, Article) }
|
66
|
-
specify { @ability.should_not be_allowed_to(:write, Post) }
|
67
|
-
|
68
|
-
its(:user_account) { should be_a(UserAccount) }
|
69
|
-
its(:user) { should be_a(User) }
|
20
|
+
subject { CanTango::Ability::Base.new @account }
|
70
21
|
|
71
|
-
|
72
|
-
its(:role_groups) { should_not be_empty }
|
22
|
+
specify { subject.should be_allowed_to(:edit, Project) }
|
73
23
|
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'fixtures/models'
|
3
|
+
|
4
|
+
describe CanTango::Ability::Cache::SimpleKey do
|
5
|
+
before do
|
6
|
+
@user = User.new 'krisy', 'krisy@gmail.com'
|
7
|
+
@account = Account.new user
|
8
|
+
@ability = CanTango::Ability::Base.new @account
|
9
|
+
end
|
10
|
+
|
11
|
+
context 'SimpleKey for user' do
|
12
|
+
subject { CanTango::Ability::Cache::SimpleKey.new @user }
|
13
|
+
|
14
|
+
specify do
|
15
|
+
subject.value.should == @user.email.hash
|
16
|
+
end
|
17
|
+
|
18
|
+
specify do
|
19
|
+
subject.to_s.should match /#{@user.email.hash}/
|
20
|
+
end
|
21
|
+
|
22
|
+
context '#Simplekey #create_for Ability' do
|
23
|
+
subject { CanTango::Ability::Cache::SimpleKey.create_for @ability }
|
24
|
+
|
25
|
+
specify do
|
26
|
+
subject.value.should == @user.email.hash
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -1,67 +1,27 @@
|
|
1
|
-
require '
|
2
|
-
require 'cantango'
|
1
|
+
require 'spec_helper'
|
3
2
|
require 'fixtures/models'
|
4
|
-
require 'cantango/rspec'
|
5
3
|
|
6
|
-
|
7
|
-
|
8
|
-
end
|
9
|
-
|
10
|
-
CanTango.configure do |config|
|
11
|
-
config.clear!
|
12
|
-
config.ability.mode = :no_cache
|
13
|
-
end
|
14
|
-
|
15
|
-
class MyExecutor
|
16
|
-
include CanTango::Ability::Executor
|
17
|
-
|
18
|
-
attr_reader :ability
|
19
|
-
|
20
|
-
def initialize ability
|
21
|
-
@ability = ability
|
22
|
-
end
|
23
|
-
|
24
|
-
def valid?
|
25
|
-
true
|
26
|
-
end
|
27
|
-
|
28
|
-
def cache_key
|
29
|
-
:my_exec
|
30
|
-
end
|
31
|
-
|
32
|
-
def permit_rules
|
33
|
-
ability.permit_rules
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
module CanTango
|
38
|
-
class Ability
|
4
|
+
module CanTango::Ability
|
5
|
+
class Base
|
39
6
|
def permit_rules
|
40
|
-
can :
|
7
|
+
can :read, Post
|
41
8
|
end
|
42
9
|
end
|
43
10
|
end
|
44
11
|
|
45
|
-
describe CanTango::Ability::Executor do
|
46
|
-
context '
|
47
|
-
let (:ability) do
|
48
|
-
CanTango::Ability.new @user
|
49
|
-
end
|
50
|
-
|
12
|
+
describe CanTango::Ability::Executor::Base do
|
13
|
+
context 'non-cached only' do
|
51
14
|
before do
|
52
|
-
@user = User.new '
|
15
|
+
@user = User.new 'admin', 'admin@mail.ru'
|
53
16
|
end
|
54
17
|
|
55
|
-
subject {
|
18
|
+
subject { CanTango::Ability::Executor::Base.new @user }
|
56
19
|
|
57
|
-
|
58
|
-
before do
|
59
|
-
subject.execute!
|
60
|
-
end
|
20
|
+
its(:non_cached_rules) { should_not be_empty }
|
61
21
|
|
62
|
-
|
22
|
+
describe 'rules contain only non-cached rules' do
|
23
|
+
specify { subject.rules.size.should == @abil.non_cached_rules.size }
|
24
|
+
specify { subject.rules.size.should == 1 }
|
63
25
|
end
|
64
26
|
end
|
65
27
|
end
|
66
|
-
|
67
|
-
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'fixtures/models'
|
3
|
+
|
4
|
+
class MyExecutor < CanTango::Ability::Executor::Base
|
5
|
+
attr_reader :ability
|
6
|
+
|
7
|
+
def initialize ability
|
8
|
+
super
|
9
|
+
end
|
10
|
+
|
11
|
+
def valid?
|
12
|
+
true
|
13
|
+
end
|
14
|
+
|
15
|
+
def cache_key
|
16
|
+
:my_exec
|
17
|
+
end
|
18
|
+
|
19
|
+
def permit_rules
|
20
|
+
ability.permit_rules
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
module CanTango::Ability
|
25
|
+
class Base
|
26
|
+
def permit_rules
|
27
|
+
can :edit, Project
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
describe CanTango::Ability::Executor::Base do
|
33
|
+
context 'Custom executor inheriting from Base' do
|
34
|
+
before do
|
35
|
+
@user = User.new 'kris'
|
36
|
+
@ability = CanTango::Ability::Base.new @user
|
37
|
+
end
|
38
|
+
|
39
|
+
subject { MyExecutor.new @ability }
|
40
|
+
|
41
|
+
describe '#execute!' do
|
42
|
+
before do
|
43
|
+
subject.execute!
|
44
|
+
end
|
45
|
+
|
46
|
+
specify { subject.ability.send(:rules).should_not be_empty }
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
|