2

最終更新: 2013 年 8 月 29 日 18:54 EST

次のモジュールを定義して、モデルに含めました。ユーザーに役割を与えるために roify gem を使用しています。

module Permissions::Offer
  extend ActiveSupport::Concern

  included do
    # `user` is a context of security
    protect do |user, offer|
      # Admins can retrieve anything
      if user.has_role? :administrator
        scope { all }

        # ... and view, create, update, or destroy anything
        can :view
        can :create
        can :update
        can :destroy
      elsif user.present?
        # Allow to read any field
        can :view
        can :create

        # Checks offered_by_id keeping possible nil in mind
        # Allow sellers to modify/delete their own offers
        if offer.try(:offered_by_id) == user.id
          can :update
          can :destroy
        end
      else
        # Guests can't read the text
        cannot :view
      end
    end
  end
end

私が経験しているのは、次のことを行うときです...

respond_with Offer.restrict!(current_user)

返されるすべてのオファーについてロール テーブルを照会します。オファーのリストを要求するときに、この要求を繰り返し行わないようにする方法はありますか? データベースへのヒットを回避するために応答をキャッシュできると確信していますが、キャッシュにもヒットしない方がよいでしょう。

Rails コンソールを開いて次の操作を行うと、同じ結果が得られます。

current_user = User.first

Offer.restrict!(current_user).to_a

Bullet gem をインストールして、N+1 クエリと見なされるかどうかを確認しましたが、検出されません。オファーの新しいインスタンスが作成されるたびに含まれているものが呼び出され、この呼び出しを開始して権限を確認するためだと思います。これは、rolify がそのユーザー ロール チェックを一定時間キャッシュしないという事実と相まって、これを理想的とは言えません。roify は、キャッシュのクリアに対処することなく、その場でロールを変更できるようにするためにこれを行うと思います。今のところ、これを解決する唯一の方法は、独自のキャッシュを実装することです。

4

1 に答える 1

2

彼らがより永続的な解決策を作成することに興味があるかどうかを確認するために、私は roify で問題を開きました。これに遭遇した他の人のために、これが私がその間に行ったことです.

def has_role?(role)
  roles = Rails.cache.fetch(roles_for: { object_id: self.object_id }, expires_in: 10.seconds, race_condition_ttl: 2.seconds) { self.roles.map(&:name) }
  roles.include?(role)
end

これは、実際のメソッドが行うすべてのことを行うわけではありません..しかし、それは私の目的に合っています。

これは、すべてのメソッドでこのようなものを実装したい人のためのソースへのリンクです。

https://github.com/EppO/rolify/blob/master/lib/rolify/role.rb

于 2013-08-30T00:43:57.587 に答える