0

ユーザー has_many constructusers。後者は has_many :through 関係の結合テーブルであり、Construct です。アプリケーションの目的で、結合テーブル (constructusers.manager、constructusers.operator など) でブール ロールが定義されますが、admin はユーザー属性です。

したがって、アクションのポリシーを定義するときが来ると、関係が認識されている間、「manager」に対して次のメソッド エラーがスローされます ActiveRecord::Relation:0x000001035c4370

  def show?
    user.admin? or user.constructusers.manager?
  end

関係(適切なものだと思います)が正しい場合、ブール属性が認識されないのはなぜですか?

以下のコメントによると、単純な理由で複数形です。したがって、フィルタリングには次のものが必要です。

Constructuser.where(['construct_id = ? and user_id = ?', params[:id], current_user]).first

...コントローラーで実行され、ビューに影響を与えます。それにもかかわらず、Pundit を適切に処理するには、これを除外する必要があります...まだ、その属性を設定する前のフィルターで application_controller を使用します。ただし、その検索条件を使用した before_filter :set_constructuser_manager は、nil ケースの処理を使用して、ポリシーを記述するときに影響を与えません。

  def show?
    set_constructuser_manager?
  end

更新:以下のコメントに従って。Pundit クラスのプライベート メソッド

def contractorconstruct 
  @contructs = Construct.where(['constructusers.user_id = ?', user]).joins(:users).all
  @contractorconstruct ||= Contractor.where(['construct_id IN (?)', @contructs]).first
end

およびアクション ルール

|| contractorconstruct?

メソッド エラーは返されません。

4

1 に答える 1

1

manager?リレーションではなく、Constructuser のインスタンスのメソッドになります。「このconstructusersはmanagerですか?」という質問について考えてみてください。- 意味がない。コンピューターは、あなたが話しているコンストラクトユーザーをどのように知るのでしょうか?

ユーザーが多数のコンストラクトユーザーを持っている場合、使用するmanager?には、関心のあるインスタンスを見つける必要があります。これが ConstructPolicy にある場合は、承認しているコンストラクトにリンクする特定のコンストラクトユーザーを見つけて、userその単一のコンストラクトユーザーがmanager?.

Construct コントローラーにいる場合は、次のようなものがあります。

class ConstructsController

  before_action :set_construct

  def show
    authorize @construct
    # ...
  end

  # ...

end

あなたのポリシーではuser、現在のユーザーになり、recordになります@construct

class ConstructPolicy

  def show?
    user.admin? || constructuser.manage?
  end

  private

    def constructuser 
      @constructuser ||= Constructuser.find_by(user_id: user, construct_id: record)
    end

end
于 2013-11-28T16:09:53.180 に答える