【发布时间】:2013-09-10 20:50:36
【问题描述】:
我在我的应用程序中使用了 devise 和 cancan。我的 Product model 有一个 belong_to :user 并且 User 表 有一个列 seller:boolean。因此,在我的能力类中,我有这一行 product.try(:user).seller 如粘贴在问题中的能力类所示,该行在 ProductsController#create, undefined method 中抛出 NoMethodError每当我尝试创建新产品时,nil:NilClass 的`seller'。但是在 controllers create action 中,user object 是 not nil 因为当我在错误后检查日志时,我看到 SELECT "users".* FROM "users" WHERE "users"."id" = 11.
另外,如果我这样做,在 Rails 控制台中:
a = Product.find(4)
a.user.seller will return => true
我的能力等级
class Ability
include CanCan::Ability
def initialize(user)
user ||= User.new
can :manage, Product do | product |
product.try(:user_id) == user.id
product.try(:user).seller == true
end
end
end
产品控制器:
class ProductsController < ApplicationController
before_filter :authenticate_user!, except: [:index, :show]
load_and_authorize_resource only: [:create, :edit, :destroy]
respond_to :html, :json
def index
@products = Product.all
respond_with @products
end
def new
@product = Product.new
end
def create
@user = User.find_by(id: current_user.id)
@product = @user.products.build(product_params)
@product.save
end
end
为了使 CanCan 与 rails 4 一起工作,我的应用程序控制器具有
class ApplicationController < ActionController::Base
#temprary work-around for cancan gem to work with rails-4
#source https://github.com/ryanb/cancan/issues/835#issuecomment-18663815
before_filter do
resource = controller_path.singularize.gsub('/', '_').to_sym
method = "#{resource}_params"
params[resource] &&= send(method) if respond_to?(method, true)
end
end
为了让下面的截图更清晰,这里是 products/index.html.erb 的缩短版本
<% @products.each do |product| %>
<% if user_signed_in? %>
<% if can? :update, product %>
<span class="bottomcentre"><%= link_to 'edit', edit_product_path(product), class: "btn btn-primary" %></span>
<% end %>
<% if can? :destroy, product %>
<span class="bottomright"><%= link_to "Delete", product, data: {confirm: 'Are u sure?'}, method: :delete, class: "btn btn-danger" %></span>
<% end %>
<% end %><!-- closes user_signed_in -->
<% end %>
<br/>
<% if user_signed_in? %>
<% if can? :create, Product %>
<%= link_to 'Create a new Product', new_product_path %>
<% end %>
<% end %>
另一个效果是 edit 和 destroy 链接显示给卖家的产品不是他们的,除非我注释掉引发错误的行,即这个 product.try(:user).seller == true 在前面显示的 CanCan's Ability Class 中。因此,当被注释掉时,我得到这个截图 1,其中隐藏了不属于卖家的产品的编辑链接,当取消注释时,你得到截图 2,所有产品编辑链接都显示给卖家,即使产品不是他们的。
屏幕截图 1,product.try(:user).seller == true 在 CanCan Ability Class 中被注释掉,它显示了编辑链接 仅适用于属于已签名卖家的前两个产品
product.try(:user).seller == true 的屏幕截图 2 在 CanCan Ability Class 中保持原样。看到 edit links 显示为 shirt 和 cufflinks 的较低产品,它们不属于已登录卖家。
【问题讨论】:
标签: ruby-on-rails devise ruby-on-rails-4 cancan