From c663effc06a4c6af00dc1530068849fde67030f3 Mon Sep 17 00:00:00 2001 From: Ryan Bates Date: Mon, 16 Nov 2009 16:24:36 -0800 Subject: [PATCH] using instance_exec to change scope of can blocks to instance of ability, this is a bit ugly so I may end up using methods instead --- lib/cancan.rb | 1 + lib/cancan/ability.rb | 10 +++++++++- lib/cancan/instance_exec.rb | 15 +++++++++++++++ spec/cancan/ability_spec.rb | 7 +++++++ 4 files changed, 32 insertions(+), 1 deletion(-) create mode 100644 lib/cancan/instance_exec.rb diff --git a/lib/cancan.rb b/lib/cancan.rb index 6f0aed1..f2b7e7a 100644 --- a/lib/cancan.rb +++ b/lib/cancan.rb @@ -1,2 +1,3 @@ $:.unshift(File.dirname(__FILE__)) require 'cancan/ability' +require 'cancan/instance_exec' diff --git a/lib/cancan/ability.rb b/lib/cancan/ability.rb index 932029b..fde8660 100644 --- a/lib/cancan/ability.rb +++ b/lib/cancan/ability.rb @@ -1,5 +1,7 @@ module CanCan module Ability + attr_accessor :user + def self.included(base) base.extend ClassMethods base.alias_action :index, :show, :to => :read @@ -18,7 +20,7 @@ module CanCan 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 can_block.call(*block_args) + return instance_exec(*block_args, &can_block) end end end @@ -48,6 +50,12 @@ module CanCan target = args.pop[:to] @aliased_actions[target] = args end + + def for_user(user) + ability = new + ability.user = user + ability + end end end end diff --git a/lib/cancan/instance_exec.rb b/lib/cancan/instance_exec.rb new file mode 100644 index 0000000..fa28ad3 --- /dev/null +++ b/lib/cancan/instance_exec.rb @@ -0,0 +1,15 @@ +# 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 diff --git a/spec/cancan/ability_spec.rb b/spec/cancan/ability_spec.rb index ed6a77d..abefab9 100644 --- a/spec/cancan/ability_spec.rb +++ b/spec/cancan/ability_spec.rb @@ -77,4 +77,11 @@ describe CanCan::Ability do @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 + end end