Ruby on rails 具有权威gem的类别策略规范的问题

Ruby on rails 具有权威gem的类别策略规范的问题,ruby-on-rails,rspec,pundit,Ruby On Rails,Rspec,Pundit,所以我通过分类来关联类别和帖子。 我正试图用pundit gem限制访问,并用RSpec测试,以便通过一个类别显示帖子。因为有了这种联系,我就有了: c=第一类 c、 职位 我按类别显示帖子 我需要一些帮助 my categories\u controller.rb class CategoriesController < ApplicationController before_action :set_category, only: [:show] def show a

所以我通过分类来关联类别和帖子。 我正试图用pundit gem限制访问,并用RSpec测试,以便通过一个类别显示帖子。因为有了这种联系,我就有了: c=第一类 c、 职位

我按类别显示帖子

我需要一些帮助

my categories\u controller.rb

class CategoriesController < ApplicationController
  before_action :set_category, only: [:show]

  def show
    authorize @category, :show?
  end

  private

  def set_category
    @category = Category.find(params[:id])
  end
end
类别_policy.rb

class CategoryPolicy < ApplicationPolicy
  class Scope < Scope
    def resolve
      resolve
    end
  end

  def show?
    user.try(:admin?) || record.post.has_member?(user)
  end
end
我在用这个火柴。 pundit_matcher.rb

RSpec::Matchers.define :permit_action do |action|
  match do |policy|
    policy.public_send("#{action}?")
  end

  failure_message do |policy|
    "#{policy.class} does not allow #{policy.user || "nil"} to " +
      "perform :#{action}? on #{policy.record}."
  end

  failure_message_when_negated do |policy|
    "#{policy.class} does not forbid #{policy.user || "nil"} from " +
      "performing :#{action}? on #{policy.record}."
  end
end
post.rb

class Post < ActiveRecord::Base
  belongs_to :author, class_name: "User"
  has_many :roles, dependent: :delete_all
  has_many :categorizations, dependent: :destroy
  has_many :categories, through: :categorizations

  mount_base64_uploader :attachment, AttachmentUploader

  validates :title,
              presence: true,
              length: { minimum: 10, maximum: 100 },
              uniqueness: true
  validates :subtitle,
              length: { maximum: 100 }
  validates :content,
              presence: true,
              length: { minimum: 30 }
  validates :attachment, file_size: { less_than: 1.megabytes }


  def has_member?(user)
    roles.exists?(user_id: user)
  end

  [:manager, :editor, :viewer].each do |role|
    define_method "has_#{role}?" do |user|
      roles.exists?(user_id: user, role: role)
    end
  end

end
我得到这个错误:

Failure/Error: user.try(:admin?) || record.post.has_member?(user)

     NoMethodError:
       undefined method `post' for #<Category:0x007fc61bfdbf40>
       Did you mean?  posts

可以在show上按类别显示此帖子,或者我需要切换到index?

错误说明,您的类别模型没有post方法,它只有帖子。这是因为分类有很多帖子。因为record.post.has_member?您的类别策略中的用户认为record是类别实例毫无意义。因为类别似乎与用户没有直接关系,并且您的角色与用户和帖子相关联


我不清楚你的分类策略的真正目的是什么,除非它只允许用户在已经有使用该分类的帖子的情况下查看分类?如果是这种情况,那么您需要更改策略,以实际检查其中是否存在。

我的目的是按类别显示帖子。但我觉得这不是个好主意。与其这样做,最好的办法是按类别显示将发布的帖子,而不限制访问。感谢您的回复和编辑Walpole@rld是的,但您的权限完全基于帖子,而不是类别。ie-用户可以查看一个类别技术的帖子,但不能查看第二个类别技术的帖子。有了这个模型,用户可以查看一个类别吗?没什么意义。如果您确实希望策略强制执行的问题是用户是否可以查看特定类别中的任何帖子,则您需要更改查询以实际询问该问题,然后针对范围强制筛选该类别中的帖子。是的,用户可以查看具有某个类别的更多帖子。我做的分类有很多通过分类。但我只想看这些发表的帖子。而这一限制只针对职位。感谢您的回复@Thomas Walpole
require 'rails_helper'

RSpec.describe CategoryPolicy do
  context "permissions" do
    subject        { CategoryPolicy.new(user, category) }
    let(:user)     { create(:user) }
    let(:post)     { create(:post) }
    let(:category) { create(:category) }

    context "for anonymous users" do
      let(:user) { nil }

      it { should_not permit_action :show }
    end

    context "for viewers of the post" do
      before { assign_role!(user, :viewer, post) }

      it { should permit_action :show }
    end

    context "for editors of the post" do
      before { assign_role!(user, :editor, post) }

      it { should permit_action :show }
    end

    context "for managers of the post" do
      before { assign_role!(user, :manager, post) }

      it { should permit_action :show }
    end

    context "for managers of other posts" do
      before do
         assign_role!(user, :manager, create(:post))
      end

      it { should_not permit_action :show }
    end

    context "for administrators" do
      let(:user) { create(:user, :admin) }

      it  { should permit_action :show }
    end
  end
end
RSpec::Matchers.define :permit_action do |action|
  match do |policy|
    policy.public_send("#{action}?")
  end

  failure_message do |policy|
    "#{policy.class} does not allow #{policy.user || "nil"} to " +
      "perform :#{action}? on #{policy.record}."
  end

  failure_message_when_negated do |policy|
    "#{policy.class} does not forbid #{policy.user || "nil"} from " +
      "performing :#{action}? on #{policy.record}."
  end
end
class Post < ActiveRecord::Base
  belongs_to :author, class_name: "User"
  has_many :roles, dependent: :delete_all
  has_many :categorizations, dependent: :destroy
  has_many :categories, through: :categorizations

  mount_base64_uploader :attachment, AttachmentUploader

  validates :title,
              presence: true,
              length: { minimum: 10, maximum: 100 },
              uniqueness: true
  validates :subtitle,
              length: { maximum: 100 }
  validates :content,
              presence: true,
              length: { minimum: 30 }
  validates :attachment, file_size: { less_than: 1.megabytes }


  def has_member?(user)
    roles.exists?(user_id: user)
  end

  [:manager, :editor, :viewer].each do |role|
    define_method "has_#{role}?" do |user|
      roles.exists?(user_id: user, role: role)
    end
  end

end
class Role < ActiveRecord::Base
  belongs_to :user
  belongs_to :post

  def self.available_roles
    %w(manager editor viewer)
  end
end
rspec spec/policies/category_policy_spec.rb
Failure/Error: user.try(:admin?) || record.post.has_member?(user)

     NoMethodError:
       undefined method `post' for #<Category:0x007fc61bfdbf40>
       Did you mean?  posts