【问题标题】:CanCanCan Rails Not WorkingCanCanCan Rails 不工作
【发布时间】:2015-12-12 05:54:58
【问题描述】:

我正在使用带有 Devise 和 CanCanCan 的 Rails 4,由于某种原因,当我尝试只为用户制作的产品授予 CRUD 权限时,CanCanCan 权限设置均未通过,用户只能执行 阅读只有。但是,版主和管理员权限按预期工作。

ability.rb

class Ability
  include CanCan::Ability

     def initialize(user)

       user ||= User.new

    if user.is? :admin
        can :manage, :all
      elsif user.is? :moderator
        can :read, :all
        can :manage, @products
      elsif user.is? :user
        can :read, :all
        can :create, :all
        can :manage, @products do |product|
          product.try(:user) == user
        end
      else
        can :read, :all
      end
    end
  end

user.rb

  has_many :products
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable

  before_save :assign_role

  Roles = [ :admin , :moderator , :user ]

  def is?( requested_role )
    self.role == requested_role.to_s
  end

  def assign_role
    self.role = Role.find_by role: "user" if self.role.nil?
  end

.html 文件

  <% if can? :update, @products %>
  <%= link_to "Edit", edit_product_path(@product) %>
  <% end %>
  <% if can? :destroy, @products %>
  <%= link_to "Delete", product_path(@product), method: :delete, data: { confirm: "Are you sure?"} %>
  <% end %>

控制器

class ProductsController < ApplicationController
    respond_to :html, :json
    load_and_authorize_resource
    def create
        @product = current_user.products.build(product_params)
        @product.user_id = current_user.id
        if @product.save
            redirect_to products_path
        else
            render 'new'
        end
    end
        def product_params
            params.require(:product).permit(:product_name, :product_description, :user_id)
        end

编辑:

用户 SQL 表

+------------------------+--------------+------+-----+---------+----------------+
| Field                  | Type         | Null | Key | Default | Extra          |
+------------------------+--------------+------+-----+---------+----------------+
| id                     | int(11)      | NO   | PRI | NULL    | auto_increment |
| created_at             | datetime     | YES  |     | NULL    |                |
| updated_at             | datetime     | YES  |     | NULL    |                |
| email                  | varchar(255) | NO   | UNI |         |                |
| encrypted_password     | varchar(255) | NO   |     |         |                |
| reset_password_token   | varchar(255) | YES  | UNI | NULL    |                |
| reset_password_sent_at | datetime     | YES  |     | NULL    |                |
| remember_created_at    | datetime     | YES  |     | NULL    |                |
| sign_in_count          | int(11)      | NO   |     | 0       |                |
| current_sign_in_at     | datetime     | YES  |     | NULL    |                |
| last_sign_in_at        | datetime     | YES  |     | NULL    |                |
| current_sign_in_ip     | varchar(255) | YES  |     | NULL    |                |
| last_sign_in_ip        | varchar(255) | YES  |     | NULL    |                |
| role                   | varchar(255) | YES  |     | NULL    |                |
+------------------------+--------------+------+-----+---------+----------------+

产品 SQL 表

+-----------------------------------+--------------+------+-----+---------+----------------+
| Field                             | Type         | Null | Key | Default | Extra          |
+-----------------------------------+--------------+------+-----+---------+----------------+
| id                                | int(11)      | NO   | PRI | NULL    | auto_increment |
| project_goal                      | int(11)      | YES  |     | NULL    |                |
| product_name                      | varchar(255) | YES  |     | NULL    |                |
| product_description               | varchar(255) | YES  |     | NULL    |                |
| project_category                  | varchar(255) | YES  |     | NULL    |                |
...
| expiration_date                   | datetime     | YES  |     | NULL    |                |
| created_at                        | datetime     | YES  |     | NULL    |                |
| updated_at                        | datetime     | YES  |     | NULL    |                |
| user_id                           | int(11)      | YES  |     | NULL    |                |
+-----------------------------------+--------------+------+-----+---------+----------------+

这是我的文件结构

【问题讨论】:

    标签: ruby-on-rails devise cancancan


    【解决方案1】:

    而不是像这样设置一个块:

    can :manage, @products do |product|
      product.try(:user) == user
    end
    

    你可以尝试根据user_id建立权限:

    can :manage, Product do |product|
      product.user_id == user.id
    end
    

    你可以更简洁地表达这个权限:

    can :manage, Product, user_id: user.id
    

    虽然上述语法应该可以工作,但如果您遇到问题,请尝试这个稍微详细一点的版本:

    can :manage, Product, :user_id => user.id
    

    当然,这种方法假定用户和产品(产品属于用户)之间存在关系。

    另外,请记住,:manage 表示“任何操作”,因此在指定 :manage 之后定义任何 CRUD 操作和/或您的自定义方法的条件是多余的。

    最后一点,您可能想尝试使用不同的符号来表示您的标准访问级别,因为当您实际上是指用户角色时,符号 :user 很容易被误认为是用户对象。

    【讨论】:

    • 所以我尝试做can :manage, @products do |product| product.user_id == user.id end,但由于某种原因它抛出了“未定义的方法user_id' for nil:NilClass”,即使我已经在我的product_params 中定义了它。 can :manage, Product, user_id: user.id 没有抛出任何东西,只是没有用。
    • 当我写我的块样式权限时,我复制粘贴了你的一个错误,但没有发现它。请记住,@product 表示法用于指示权限是否应用于类的特定实例,而使用类名(大写、单数)指示权限是否应用于整个类。
    • 是的,我想,我尝试了两种方法,但我仍然得到同样的错误。 ://
    • “双向”是什么意思?除了最初的努力之外,您还进行了哪些尝试,目前还完全不清楚。你是如何设置角色的?您在做什么来生成该错误消息?确切地说,“只是没有工作”是什么意思?请记住,我现在并不是真的站在你身后,看着你的肩膀。我看不到你所看到的。您需要提供大量信息才能查明问题的根源,因为我提供的内容应该可以解决。
    • 两种方式都意味着我尝试将@products 和 Product 作为用户can :manage 的参数。 “角色”只是我的用户表中的一列,它通过 id 键链接到产品。我的原始块没有收到错误消息,“只是没有工作”意味着如果用户不是产品的所有者,CanCanCan 没有隐藏我在if 标签中包装的选项。我已经用我认为相关的更多信息更新了我的原始帖子,但如果我遗漏了任何信息,请告诉我,因为我想解决这个问题。
    【解决方案2】:

    你似乎在你的能力类中使用了一个实例变量。试试这个,看看它是否有效:

    class Ability
      include CanCan::Ability
    
     def initialize(user)
    
       user ||= User.new
    
    if user.is? :admin
        can :manage, :all
      elsif user.is? :moderator
        can :read, :all
        can :manage, Product # use class here not instance variable
      elsif user.is? :user
        can :read, :all
        can :create, :all
        can :manage, Product do |product| # <–-use the class here not instance variable.
          product.try(:user) == user # cancancan code examples general call ids you might wanna consider revisions?
        end
      else
        can :read, :all
      end
    end
      end
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-12-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-11-25
      • 2015-11-30
      • 1970-01-01
      相关资源
      最近更新 更多