10

ビューをキャッシュしたいのですPostが、ビューは現在のユーザーの権限によって異なります(たとえば、「編集」リンクのみを表示する場合current_user.can?(:edit, @post)

そのため、キャッシュキーに現在のユーザーのCanCan能力の表現を含めて、ユーザーの能力が変更されたときにキャッシュを無効にできるようにします。

SO:同じ能力を持つ2人の異なるユーザーが同じ「能力文字列」を生成するように、現在のユーザーの能力を表す文字列を取得するにはどうすればよいですか?

私は試しましuser.ability.inspectたが、これは同じ能力を持つ異なるユーザーに対して同じ文字列を生成しません

4

2 に答える 2

14

編集:CanCanCan用に改訂

CanCanCanのバージョン1.12(CanCanのコミュニティ継続)以降Ability.new(user).permissions、指定されたユーザーのすべての権限を持つハッシュを返します。

前の回答(CanCan):

これは少し複雑かもしれません...しかし、ここにあります。

指定したユーザーをCanCanに必要な能力モデルに渡すと、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"]

これらのルールが適用されているモデルを知りたい場合は、@subjectsインスタンス変数にアクセスしてその名前を取得できます。

これが私が使ったAbilityのモデルレイアウトです(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)]>
]
于 2012-04-13T19:20:21.137 に答える
7

私は自分の能力を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);
    });
   }
});
于 2013-01-29T18:44:41.727 に答える