ruby-on-rails - CanCan、Rails 和协作

标签 ruby-on-rails ruby authorization cancan

我有一个 Ruby on Rails 应用,包含用户文章协作。以下是关系:

User has_many :articles
User has_many :collaborations

Article belongs_to :users
Article has_many :collaborations

# Collaboration has collaboration.id collaboration.user_id and collaboration.article_id.
Collaboration belongs_to :users
Collaboration belongs_to :articles

通过协作,我成功地访问了用户和文章,所以我认为我的应用程序中的所有设置都正确无误。好的问题。

我正在使用 CanCan角色为 :admin。基本上我只希望 :admin 能够创建帖子和协作,并且我也能正常工作。问题是......我如何将该角色写入我的 ability.rb 文件,以便非管理员用户仍然可以在他们参与协作的文章中进行协作?”

  1. 用户 A(管理员)创建文章 X
  2. 用户 A 与用户 B 就文章 X 创建了协作
  3. 用户 B 登录但只能编辑和更新文章 X

我应该如何在 ability.rb 中编写它。这就像我想说的:“不是管理员的用户可以管理文章,他们是该文章协作的一部分。”

抱歉啰嗦,我还没喝咖啡:)。这是我的 ability.rb

class Ability
  include CanCan::Ability

  def initialize(user)
    user ||= User.new # guest user
    if user.role == "admin"
      can :manage, :all
    else
      can :read, Article
      # this is where I want to say: can :manage if part of collaboration for article 
    end
  end
end

最佳答案

以下是您的 Ability 类中可能适合您的逻辑:

class Ability
  include CanCan::Ability

  def initialize(user)
    user ||= User.new # guest user
    case
    when user.admin?
      can :manage, :all
    when user.registered?
      can :read, Article
      can :manage, Article, :collaborations => { :user_id => user.id }
    else # user.guest?
      can :read, Article
    end
  end
end

CanCan 允许您指定关联的条件;在这里,我们为 Article 上的 :collaborations 关联传递了 :user_id 条件。

为用户添加的附加方法:

class User < ActiveRecord::Base

  ROLES = [
    ADMIN = 'admin'
  ]

  def admin?
    role == ADMIN
  end

  def registered?
    persisted?
  end

end

为确保它正常工作,下面是您可以如何使用 RSpec、FactoryGirl 和 CanCan 匹配器编写测试:

require 'spec_helper'
require "cancan/matchers"

describe Ability do
  subject { Ability.new(user) }

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

    it { should be_able_to(:manage, :all) }
  end

  context "user" do
    let(:user) { create(:user) }

    it { should be_able_to(:read, Article) }

    it "cannot manage articles without collaborations" do
      article = create(:article)
      should_not be_able_to(:manage, article)
    end

    it "cannot manage articles only others collaborated on" do
      article = create(:article)
      article.collaborations.create { |c| c.user = create(:user) }
      should_not be_able_to(:manage, article)
    end

    it "can manage article with collobaration" do
      article = create(:article)
      article.collaborations.create { |c| c.user = user }
      should be_able_to(:manage, article)
    end
  end

  context "guest" do
    let(:user) { User.new }

    it { should be_able_to(:read, Article) }
    it { should_not be_able_to(:manage, Article) }
  end
end

关于ruby-on-rails - CanCan、Rails 和协作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12747313/

相关文章:

ruby - 如何使用 watir-webdriver 按类和文本查找元素

c# - 如何告诉 [Authorize] 属性将基本身份验证与自定义消息处理程序一起使用?

asp.net - 是否某些企业库应用程序 block 已过时?

ruby-on-rails - RSpec - 无法写入未知属性(枚举)

ruby-on-rails - 单表继承路由?

ruby-on-rails - 如何抑制 Rails 4 中的查询缓存日志记录

Ruby正则表达式方法!~

ruby-on-rails - Rails Observer 4.0 的替代方案

ruby-on-rails -::ModuleName::ClassName 和 ModuleName::ClassName 有什么区别

c# - OData WebAPI 2 复杂授权