1

だから私は次の設定をしています:

class User < AR
  has_many :memberships
  has_many :user_groups, through: :memberships
  has_many :organizations, through: :memberships
end

class Membership < AR
  belongs_to :user
  belongs_to :user_group
  belongs_to :organization
end

class UserGroup < AR
  has_many :memberships
  has_many :users, through: :memberships
  has_many user_groups, through: :memberships
end

つまり、1 人のユーザーが、組織 A ではプロダクト マネージャー、組織 B では記事マネージャーおよびコメント マネージャーになることができます。

したがって、質問できるようにするには、次can? :manage, an_article_instanceのように能力を設定する必要があります。

class Ability
  if user.is_content_manager_for(currently_selected_organization)
    can :manage, Article

  elsif user.is_admin_for(currently_selected_organization)
    can :manage, User, memberships: { organization_id: currently_selected_organization }
  end
end

バックエンドの Web インターフェイスには、ユーザーが作業したい組織を選択できる選択メニューがあるはずです。そのため、現在選択されている組織をセッションに保存することを考えていました。これは、作業セッション全体で永続的なデータであるためです。

currently_selected_organizationしかし、Ability (またはその他の) モデルで (または直接セッションに)ヘルパー メソッドにアクセスすると、実際には MVC パターンに違反します。これは良くない、などなど、いくつかの場所で読みました。

だから、これを行うためのより良い/よりクリーンな方法があるかどうか疑問に思っていますか?

4

1 に答える 1

4

わかりましたので、別のアプローチでそれを理解しました。CanCan は、新しいオブジェクトをインスタンス化してオブジェクトを渡すcurrent_abilityメソッドを追加します。独自のコントローラーでメソッドを単純に上書きできるので、最終的にこれを行いました。ActionController::BaseAbilitycurrent_usercurrent_ability

class ApplicationController < ActionController::Base
  def current_ability
    @current_ability ||= Ability.new(current_user, Organization.find_by(id: cookies[:current_organization])
  end
end

class Ability
  include CanCan::Ability

  def initialize(user, currently_selected_organization)
    if user.is_admin_for(currently_selected_organization
      # ...
    end
  end
end

このようにして、MVC パターンを壊すことはなく、ヘルパー モジュールを含めたり、何かをハッキングしたりすることもありませんでした。

于 2013-08-07T18:09:52.490 に答える