Permalink
Browse files

moving can definition into ability instance instead of class, this re…

…moves ugly instance_exec command
  • Loading branch information...
1 parent 7b299b5 commit 4b6f5386631761307e976ba74a3f39ce9d2a250d @ryanb committed Nov 17, 2009
View
1 lib/cancan.rb
@@ -2,6 +2,5 @@ module CanCan
class AccessDenied < StandardError; end
end
-require File.dirname(__FILE__) + '/cancan/instance_exec'
require File.dirname(__FILE__) + '/cancan/ability'
require File.dirname(__FILE__) + '/cancan/controller_additions'
View
54 lib/cancan/ability.rb
@@ -2,15 +2,8 @@ module CanCan
module Ability
attr_accessor :user
- def self.included(base)
- base.extend ClassMethods
- base.alias_action :index, :show, :to => :read
- base.alias_action :new, :to => :create
- base.alias_action :edit, :to => :update
- end
-
def can?(original_action, target) # TODO this could use some refactoring
- (self.class.can_history || []).reverse.each do |can_action, can_target, can_block|
+ (@can_history || []).reverse.each do |can_action, can_target, can_block|
possible_actions_for(original_action).each do |action|
if (can_action == :manage || can_action == action) && (can_target == :all || can_target == target || target.kind_of?(can_target))
if can_block.nil?
@@ -20,7 +13,7 @@ def can?(original_action, target) # TODO this could use some refactoring
block_args << action if can_action == :manage
block_args << (target.class == Class ? target : target.class) if can_target == :all
block_args << (target.class == Class ? nil : target)
- return instance_exec(*block_args, &can_block)
+ return can_block.call(*block_args)
end
end
end
@@ -30,32 +23,33 @@ def can?(original_action, target) # TODO this could use some refactoring
def possible_actions_for(initial_action)
actions = [initial_action]
- (self.class.aliased_actions || []).each do |target, aliases|
+ (@aliased_actions || default_alias_actions).each do |target, aliases|
actions += possible_actions_for(target) if aliases.include? initial_action
end
actions
end
-
- module ClassMethods
- attr_reader :can_history
- attr_reader :aliased_actions
-
- def can(action, target, &block)
- @can_history ||= []
- @can_history << [action, target, block]
- end
-
- def alias_action(*args)
- @aliased_actions ||= {}
- target = args.pop[:to]
- @aliased_actions[target] = args
- end
- def for_user(user)
- ability = new
- ability.user = user
- ability
- end
+ def can(action, target, &block)
+ @can_history ||= []
+ @can_history << [action, target, block]
+ end
+
+ def alias_action(*args)
+ @aliased_actions ||= default_alias_actions
+ target = args.pop[:to]
+ @aliased_actions[target] = args
+ end
+
+ def default_alias_actions
+ {
+ :read => [:index, :show],
+ :create => [:new],
+ :update => [:edit],
+ }
+ end
+
+ def prepare(user)
+ # to be overriden by included class
end
end
end
View
4 lib/cancan/controller_additions.rb
@@ -9,7 +9,9 @@ def unauthorized!
end
def current_ability
- ::Ability.for_user(current_user)
+ ability = ::Ability.new
+ ability.prepare(current_user)
+ ability
end
def can?(*args)
View
15 lib/cancan/instance_exec.rb
@@ -1,15 +0,0 @@
-# see http://eigenclass.org/hiki.rb?instance_exec
-class Object
- module InstanceExecHelper; end
- include InstanceExecHelper
- def instance_exec(*args, &block) # !> method redefined; discarding old instance_exec
- mname = "__instance_exec_#{Thread.current.object_id.abs}_#{object_id.abs}"
- InstanceExecHelper.module_eval{ define_method(mname, &block) }
- begin
- ret = send(mname, *args)
- ensure
- InstanceExecHelper.module_eval{ undef_method(mname) } rescue nil
- end
- ret
- end
-end
View
31 spec/cancan/ability_spec.rb
@@ -8,7 +8,7 @@
end
it "should be able to :read anything" do
- @ability_class.can :read, :all
+ @ability.can :read, :all
@ability.can?(:read, String).should be_true
@ability.can?(:read, 123).should be_true
end
@@ -18,70 +18,67 @@
end
it "should return what block returns on a can call" do
- @ability_class.can :read, :all
- @ability_class.can :read, Symbol do |sym|
+ @ability.can :read, :all
+ @ability.can :read, Symbol do |sym|
sym
end
@ability.can?(:read, Symbol).should be_nil
@ability.can?(:read, :some_symbol).should == :some_symbol
end
it "should pass class with object if :all objects are accepted" do
- @ability_class.can :preview, :all do |object_class, object|
+ @ability.can :preview, :all do |object_class, object|
[object_class, object]
end
@ability.can?(:preview, 123).should == [Fixnum, 123]
end
it "should pass class with no object if :all objects are accepted and class is passed directly" do
- @ability_class.can :preview, :all do |object_class, object|
+ @ability.can :preview, :all do |object_class, object|
[object_class, object]
end
@ability.can?(:preview, Hash).should == [Hash, nil]
end
it "should pass action and object for global manage actions" do
- @ability_class.can :manage, Array do |action, object|
+ @ability.can :manage, Array do |action, object|
[action, object]
end
@ability.can?(:stuff, [1, 2]).should == [:stuff, [1, 2]]
@ability.can?(:stuff, Array).should == [:stuff, nil]
end
it "should alias update or destroy actions to modify action" do
- @ability_class.alias_action :update, :destroy, :to => :modify
- @ability_class.can :modify, :all do |object_class, object|
+ @ability.alias_action :update, :destroy, :to => :modify
+ @ability.can :modify, :all do |object_class, object|
:modify_called
end
@ability.can?(:update, 123).should == :modify_called
@ability.can?(:destroy, 123).should == :modify_called
end
it "should return block result for action, object_class, and object for any action" do
- @ability_class.can :manage, :all do |action, object_class, object|
+ @ability.can :manage, :all do |action, object_class, object|
[action, object_class, object]
end
@ability.can?(:foo, 123).should == [:foo, Fixnum, 123]
@ability.can?(:bar, Fixnum).should == [:bar, Fixnum, nil]
end
it "should automatically alias index and show into read calls" do
- @ability_class.can :read, :all
+ @ability.can :read, :all
@ability.can?(:index, 123).should be_true
@ability.can?(:show, 123).should be_true
end
it "should automatically alias new and edit into create and update respectively" do
- @ability_class.can(:create, :all) { :create_called }
- @ability_class.can(:update, :all) { :update_called }
+ @ability.can(:create, :all) { :create_called }
+ @ability.can(:update, :all) { :update_called }
@ability.can?(:new, 123).should == :create_called
@ability.can?(:edit, 123).should == :update_called
end
- it "should be able to access given user" do
- @ability_class.can(:preview, :all) { user }
- ability = @ability_class.for_user(:some_user)
- ability.user.should == :some_user
- ability.can?(:preview, 123).should == :some_user
+ it "should respond to prepare" do
+ @ability.should respond_to(:prepare)
end
end
View
1 spec/cancan/controller_additions_spec.rb
@@ -21,7 +21,6 @@ class Ability
it "should have a current_ability method which generates an ability for the current user" do
stub(@controller).current_user { :current_user }
@controller.current_ability.should be_kind_of(Ability)
- @controller.current_ability.user.should == :current_user
end
it "should provide a can? method which goes through the current ability" do

0 comments on commit 4b6f538

Please sign in to comment.