2012-03-21 47 views
7

我想緩存Post視圖中的字符串,但認爲取決於當前用戶的權限(例如,我只顯示,如果current_user.can?(:edit, @post)「編輯」鏈接)獲取表示用戶的康康舞能力

所以我希望我的緩存鍵包含當前用戶CanCan能力的表示形式,以便在用戶能力發生變化時使緩存失效

SO:如何獲取表示當前用戶能力的字符串,例如: 2個具有相同能力的不同用戶會產生相同的「能力串」?

我試過user.ability.inspect,但這不會產生誰擁有相同的能力

+0

錯過了賞金! :( – RGB 2012-04-16 13:28:01

回答

7

編輯不同的用戶相同的字符串:修訂CanCanCan

由於CanCanCan的1.12版本( CanCan的社區延續),Ability.new(user).permissions返回一個包含給定用戶所有權限的散列。

以前的答案(康康舞):

這可能是一個有點複雜......但在這裏不用..

如果通過指定用戶到由慘慘,你所需要的能力模型可以訪問使用instance_variable_get用戶角色的定義,然後把它分解成任何字符串值,你從那裏想..

>> u=User.new(:role=>"admin") 
>> a=Ability.new(u) 
>> a.instance_variable_get("@rules").collect{ 
     |rule| rule.instance_variable_get("@actions").to_s 
    } 
=> ["read", "manage", "update"] 

,如果你想知道在這些規則是在模型在flicted,您可以訪問@subjects實例變量來得到它的名字..

這裏是能力模型結構,從我與(PP)

Ability:0x5b41dba @rules=[ 
    #<CanCan::Rule:0xc114739 
    @actions=[:read], 
    @base_behavior=true, 
    @conditions={}, 
    @match_all=false, 
    @block=nil, 
    @subjects=[ 
     User(role: string)]>, 
    #<CanCan::Rule:0x7ec40b92 
    @actions=[:manage], 
    @base_behavior=true, 
    @conditions={}, 
    @match_all=false, 
    @block=nil, 
    @subjects=[ 
     Encounter(id: integer)]>, 
    #<CanCan::Rule:0x55bf110c 
    @actions=[:update], 
    @base_behavior=true, 
    @conditions={:id=>4}, 
    @match_all=false, 
    @block=nil, 
    @subjects=[ 
     User(role: string)]> 
] 
+0

我想總結一下,你將不得不建立與你選擇的內容,保存它,然後將其內容轉換爲使用to_s字符串的數組!:) – RGB 2012-04-13 19:27:30

+0

這是一個黑客依靠實施細節。 – tmandry 2015-01-05 22:12:05

+0

唯一依賴的是用戶正在使用CanCan gem,這是OP正在使用的。當使用CanCan時,能力和用戶類別固有可用 – RGB 2015-01-05 22:33:52

5

我想送我的能力的工作JS和後續的這篇文章,這裏是我的助手方法,你可以用它來將你的用戶能力轉換爲控制器中的數組。然後我在數組上調用.to_json並將其傳遞給javascript。

def ability_to_array(a) 
    a.instance_variable_get("@rules").collect{ |rule| 
    { 
    :subject => rule.instance_variable_get("@subjects").map { |s| s.name }, 
    :actions => rule.instance_variable_get("@actions").map { |a| a.to_s } 
    } 
} 
end 

下面是一個實現了CAN()方法我Backbone.js的模型:

var Abilities = Backbone.Model.extend({ 
    can : function(action, subject) 
    { 
    return _.some(this.get("abilities"), function(a) { 
     if(_.contains(a["actions"], "manage") && _.contains(a["subject"], "all")) return true; 
     return _.contains(a["actions"], action) && _.contains(a["subject"], subject); 
    }); 
    } 
}); 
+0

您也可以使用:subject => rule.instance_variable_get(「@ subjects」)。map {| s | s.to_s},就好像你使用s.name一樣,你的主題包含符號會出錯 – SteveA 2014-02-21 10:51:53

相關問題