Techioz Blog

can などの CanCanCan のメソッドにアクセスするより良い方法はありますか?モデルで?

概要

CanCanCan のメソッドはコントローラーまたはビューでのみ使用できますが、モデル内、具体的にはモデルの save メソッド内でアクセスしたいと考えています。この問題に対して私が使用する回避策は次のとおりです。save を呼び出す前に、モデル内に attr_accessor :ability を作成し、コントローラー内でそれに Abability オブジェクトを割り当てます。

class Example
  include ActiveModel::Model

  attr_accessor :ability

  def save
    if ability.can?(:create, SomeOtherModel)
       ...
    end
  end

end
class ExamplesController < ApplicationController
  def create
    @example = Example.new(params[:example])
    @example.ability = Ability.new(current_admin_user) #note: current_admin_user can be several separate models such as Admin, Support

    if @example.save
      ...
    end
  end

end

can を呼び出すより良い方法はありますか?モデル内から?セキュリティの観点などから、このソリューションに問題はありますか?

解決策

モデルにアビリティ メソッドを追加して、can? を委任することもできます。方法:

# app/models/user.rb
class User
  delegate :can?, :cannot?, to: :ability

  def ability
    @ability ||= Ability.new(self)
  end
end

some_user.can? :update, @article

https://translate.google.com/translate?hl=ja&sl=en&tl=ja&u=https://github.com/CanCanCommunity/cancancan/blob/develop/docs/define_check_abilities.md

この解決策では、能力をチェックする必要があるすべてのモデルで能力メソッドを定義する必要があると思います。そのため、コードが重複する可能性があります。

セキュリティの観点からは、予期せぬ事態を招く可能性があります。コントローラーは、モデルの許可された属性のみを作成/更新する強力なパラメーターをすでにサポートしています。

たとえば、サポートが一部の属性のみを更新でき、管理者がすべての属性を更新できる場合、モデル内でそれをどのように制御しますか?

また、コントローラーで能力をチェックすると、ユーザーのアクションを防止し、サーバーへの不要なクエリを回避できます。

CanCan がコントローラーとビューで can メソッドが最適に機能することを推奨している理由は次のとおりだと思います。

https://translate.google.com/translate?hl=ja&sl=en&tl=ja&u=https://github.com/CanCanCommunity/cancancan/blob/develop/docs/controller_helpers.md