简体   繁体   English

Rails-4,CanCan为nil:NilClass返回未定义的方法,用于存在的用户模型属性

[英]Rails-4, CanCan returning undefined method for nil:NilClass, for a user model attribute that exists

I am using devise and cancan in my app. 我在我的应用程序中使用设计和cancan。 My Product model has a belong_to :user and the User table has a column seller:boolean . 我的产品型号有一个belongs_to:user ,而User表有一个列卖家:boolean So in my ability class I have this line product.try(:user).seller as shown in the Ability Class pasted in the question, that line throws NoMethodError in ProductsController#create, undefined method `seller' for nil:NilClass any time I try to create a new product. 所以在我的能力课中,我有这行product.try(:user).seller ,如问题中粘贴的能力类所示,该行在ProductsController中创建NoMethodError #infine,未定义方法`seller'为nil:NilClass任何时候我尝试创建一个新产品。 But in the controllers create action , the user object is not nil because when I inspect the log after the error, I see SELECT "users".* FROM "users" WHERE "users"."id" = 11 . 但是在控制器创建动作时用户对象 不是零,因为当我在错误之后检查日志时,我看到SELECT“users”。* FROM“users”WHERE“users”。“id”= 11

Also, in the rails console if I do: 另外,在rails控制台中如果我这样做:

   a = Product.find(4)    
   a.user.seller  will return  => true   

My ability class 我的能力课

 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   

The Productscontroller: 产品控制器:

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  

To make CanCan work with rails 4, my application controller has 为了使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

To give clarity to the screenshots below, here is a shortened version of products/index.html.erb 为了清楚下面的屏幕截图,这里是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 %>

An additional effect is that the edit and destroy links are shown to a seller for products that are not theirs unless I comment out the line raising the error, that is this product.try(:user).seller == true in the CanCan's Ability Class shown earlier on. 另一个影响是编辑销毁链接会向卖家显示不属于他们的产品,除非我注释掉引发错误的行,即此产品。(:user).seller ==CanCan的能力中为前面所示的 So when commented out, I get this screenshot 1 with edit links hidden fro products not belongs to the seller and when uncommented you get screenshot 2, with all product edit link displayed to a seller, even if the products are not theirs. 因此,当注释掉时,我得到这个屏幕截图1,其中隐藏的产品不属于卖家的编辑链接,当取消注释时,您会获得屏幕截图2,所有产品编辑链接显示给卖家,即使产品不是他们的。

screenshot 1 with product.try(:user).seller == true commented out in the CanCan Ability Class , and it shows the edit link for only the first two product which belongs to the signed_in seller 截图1 with product.try(:user).seller == trueCanCan Ability Class中注释掉,它只显示属于signed_in卖家的前两个产品的编辑链接 在此输入图像描述

screenshot 2 with product.try(:user).seller == true left intact in the CanCan Ability Class . 截图2 with product.try(:user).seller == trueCanCan Ability Class中保持不变。 see edit links being displayed for the lower products that is shirt and cufflinks and they don't belong to the signed_in seller. 查看针对衬衫袖扣的较低产品显示的编辑链接 ,它们不属于signed_in卖家。 在此输入图像描述

Your can :manage block definition is slightly wrong. can :manage块定义略有错误。 It is the return value of the block that determines whether the user has the ability or not. 它是块的返回值,用于确定用户是否具有该能力。 In your block you have two statements of which only the second will have any bearing on whether the user has the ability. 在您的块中,您有两个语句,其中只有第二个语句与用户是否具有该能力有关。 You need to join your statements with && . 您需要使用&&加入您的陈述。

Also, your error seems to be when a product has no user as opposed to when the current user is nil. 此外,您的错误似乎是当产品没有用户而不是当前用户为零时。 You need to use try on the return of product.try(:user) too as it will be nil if there is no product. 你需要try返回product.try(:user)因为如果没有产品,它将是零。

So, all told I think your block needs to be: 所以,所有人告诉我,我认为你的块需要:

can :manage, Product do | product |
  product.try(:user_id) == user.id &&
  product.try(:user).try(:seller) == true 
end

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM