为什么在进行能力检查时没有显示数据?(rails,cancancan)

时间:2017-07-20 06:24:07

标签: ruby-on-rails ruby devise cancan cancancan

我想在我的rails应用程序中使用3个用户级别作为Admin,Manager,Customer。因此,我创建了一个设计模型作为用户,并添加了迁移以向其添加用户角色。因此,当用户注册时,它会存储用户角色(无论他是管理员,经理还是客户)。在我的应用程序中,有产品,交付,服务的模型和控制器。我想为每个模型设置访问级别。

因此,管理员可以访问所有模型,控制器

经理可以访问产品,交付

客户可以访问服务

我已经写了如下能力模型

class Ability
  include CanCan::Ability

  def initialize(user)

    user ||= User.new # guest user (not logged in)

    if user.roles == "admin"
      can :manage , :all
    elsif user.roles == "manager"
      can :read, Products, Delivery
    elsif user.roles == "customer"
      can :read, Services
    end
end
end

在我的产品展示视图中,我提供了以下代码

<% if can? :manage ,@products%>

<h1>Products</h1>

<% @products.each do |product| %>
<p>     <%= product.name%>
<p>         <%= product.price %><br>
<p>    <%= product.qty %><br>

  <%end%>
<%end%>

但即使我作为管理员登录我也看不到内容。但是当我删除能力检查行时,可以查看它而没有任何问题。所以我预测问题应该是这样的使用了授权。 我的用户模型如下。

    class User < ApplicationRecord
  belongs_to :role
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable

         ROLES = %i[admin manager customer]
def user_params
  params.require(:user).permit(:name, :email, :password, :password_confirmation, :role)
end

end

在views / devise / registrations / new.html.erb中 我已经包含以下代码块。

<div>
    <%= f.collection_select(:role, User::ROLES, :to_s, lambda{|i| i.to_s.humanize}) %>
  </div>

这是我必须检查我的产品/展示视图中的能力

<% if can? :manage ,@products%>

<h1>Products</h1>

<% @products.each do |product| %>
<p>     <%= product.name%>
<p>         <%= product.price %><br>
<p>    <%= product.qty %><br>

  <%end%>
<%end%>

1 个答案:

答案 0 :(得分:1)

user.roles返回一个数组,您正在将数组与字符串user.roles == "admin"进行比较,该字符串始终为false

而是使用User模型中的方法(例如user.role?(:admin))来检查角色

所以你的能力应该是

class Ability
  include CanCan::Ability

  def initialize(user)
    user ||= User.new # guest user (not logged in)
    if user.role? :admin
      can :manage, :all
    elsif user.role? :manager
      can :read, [Product, Delivery]
    elsif user.role? :customer
      can :read, Service
    end
  end
end

现在在你的控制器中你应该写一些谎言

class ProductsController < ActionController
  load_and_authorize_resource

  def index
  ...
  end

  # and other resouceful actions
end

load_and_authorize_resource做了很多魔术,其中一个加载了current_user(设计用户)可以访问的所有产品。

现在,您不必明确检查<% if can? :manage ,@products%>@products将只包含当前用户有权访问的产品。

<h1>Products</h1>
<%@products.present?%>
   <% @products.each do |product| %>
    <p><%= product.name %></p>
    <p><%= product.price %></p>
    <p><%= product.qty %></p>
  <%end%>
<%else%>
  <p>There are no products to display.</p>
<%end%>