2017-03-24 6 views
0

Rubyの新機能で、社内アプリケーションの変更に取り組んでいます。CanCanを入れ子にした子要素

CanCanを使用して、ページへのアクセスを制限することができます。

私は以下のコードを使用していますが、未知の量の子要素に対してこれを書くことができるより良い方法があることはわかっています。

ユーザには、ラインマネージャがあります。ラインマネージャは、e.t.cです。私はトップレベルのマネージャーがスタッフのアカウントを見ることができるようにツリー階層を達成しようとしていますが、スタッフの階層の一部である場合に限ります。以下の例では、JaneとJackのプロファイルは表示できますが、JoshやJamesのプロファイルは表示できません。これは、巣の量を拡大することができるよう、長期的な解決策ではなく、単にユーザーよりも上で行うことが必要とAbility.rb

class Ability 
    include CanCan::Ability 
    def initialize(user) 
     user ||= User.new 
     can :read, User, id: user.id 
     can :read, User, line_manager: user 
     can :read, User, line_manager: {line_manager: user} 
     can :read, User, line_manager: {line_manager: {line_manager: user}} 
     can :read, User, line_manager: {line_manager: {line_manager: {line_manager: user}}} 
     can :read, User, line_manager: {line_manager: {line_manager: {line_manager: {line_manager: user}}}} 
     can :read, User, line_manager: {line_manager: {line_manager: {line_manager: {line_manager: {line_manager: user}}}}} 

+-------------+----------------------+--------+ 
    | user_id  | name     | parent | 
    +-------------+----------------------+--------+ 
    |   1 | JOHN SMITH   | NULL | 
    |   2 | JANE SMITH   |  1 | 
    |   3 | JACK SMITH   |  2 | 
    |   4 | JOSH SMITH   |  5 | 
    |   5 | JAMES SMITH   | NULL | 
    +-------------+----------------------+--------+ 

パートは私がどのような援助に感謝します。

+0

のようなあなたのカンカンの能力にブロックを渡すことができます? – Gaston

答えて

0

パフォーマンス上の解決策は、dbからすべてのIDを配列で収集し、ユーザーにアクセスさせることです。

can :read, User.all do |r_user| 
    until r_user.line_manager.nil? do |manager| 
    return true if manager == user 
    r_user = manager 
    end 
    return false 
end 

(コード注テストされていないが、このようなものが動作するはずです):DB-クエリのない汚いソリューションは、ようなものになるだろう。 しかし、これはすべてのユーザーを何度も繰り返します。 idをクエリで収集することをお勧めします。

+0

Doktorに感謝します。あなたが配列で言及したように私はIDを収集し、繰り返しました。 –

+0

お受け取りいただきありがとうございます。そして、私は本当にポイントを危険にさらすのは好きではありませんが、私の答えはIDを収集するという点ではあまりありませんでした。だから私はあなたの現在のソリューションであなたの質問を更新することをお勧めします、多分それをさらに改善するのを助けることができます。それはすでに良い解決策であれば、私はあなたを助けてうれしいでしょう;-) –

0

closure_tree gemを使用すると、モデルの階層を管理できます。その後、あなたはこのようなあなたのモデルでは、インスタンスメソッドを追加することができます。

def managed_by? user_id 
    self_and_ancestors_ids.include? user_id 
end 

そして、あなたはあなたのユーザーとラインマネジャークラス定義を投稿することができますが、この

can :read, User, User.all do |fetched_user| 
    fetched_user.managed_by? user.id 
end 
関連する問題