我想检查当前对象的user-id是否与当前用户的id相同,因此我只允许对登录用户进行一些操作。我正在使用Devise gem来帮助我进行身份验证。
那就是说,我想提出一个范围更广的问题。我有构建关联,至少我是这么认为的,但是当我在浏览器中打开相应的页面时,我得到错误:
undefined method 'user' for nil:NilClass
我知道当数据库中的特定对象未实例化或没有条目时,通常会发生此错误,但我使用控制台和PostgreSQL GUI工具来检查数据是否存在。
首先要澄清我理解正确,这里有些事情是这样做的:
现在我有一个图像模型:
class Image < ActiveRecord::Base
mount_uploader :image, ImageUploader
belongs_to :user
belongs_to :game, inverse_of: :images
end
用户模型如下所示:
class User < ActiveRecord::Base
...
has_many :images
has_many :games
validates :first_name, :last_name, presence: true
end
在相应的图像控制器中,我使用:
class ImagesController < ApplicationController
before_action :set_image, only: [:show, :edit, :update, :destroy]
before_action :set_game
before_action :authenticate_user!
before_action :check_user
...
private
def set_image
@image = Image.find(params[:id])
end
def set_game
@game = Game.all
end
def check_user
unless (@image.user == current_user) || (current_user.admin?)
redirect_to root_url, alert: "Sorry but you are not allowed to visit this page."
end
end
def image_params
params.require(:image).permit(:title, :alt, :desc, :image, :category)
end
end
使用@image.user
方法中的check_user
,我会尝试获取用户的ID。如果我只使用current_user.admin?
它可行,但显然不是预期的。
正如您在上面的屏幕截图中看到的那样,user_id
字段已填充,因此我不知道为什么会出现此错误。也许我忘记了什么?
答案 0 :(得分:0)
根据您的错误消息,问题出现在@image.user
方法的check_user
上。在此,@image
为nil
。你应该检查那里是否有@image.nil?
。
可能会将其更改为:
@image = Image.find(params[:id])
unless !@image.nil? && ((@image.user == current_user) || (current_user.admin?))
顺便说一下,你应该只检查:show, :edit, :update, :destroy
中的用户:
before_action :check_user, only: [:show, :edit, :update, :destroy]
答案 1 :(得分:0)
你问的是authorization
。
- 身份验证 - 用户是否存在?
- 授权 - 用户是否有权限?
Devise提供身份验证,而授权没有Rails的“标准”流程。
您要问的是基于Rails的应用程序中授权的基线要求。解决此问题的方法是使用其中一个授权gem,即CanCanCan
或Pundit
,以确保用户可以更改所需的对象。
我个人设置授权如下:
#Gemfile
gem 'cancancan'
#app/models/ability.rb
class Ability
include CanCan::Ability
def initialize(user)
user ||= User.new # guest user (not logged in)
can :read, Image, user_id: user.id
end
end
这样您只需拨打can? :read, @image
即可验证用户的授权。
<强>修正强>
您遇到的真正问题是,您尝试在不存在的变量上调用.user
。
for nil:NilClass
当您看到上述错误时,表示您正在对未声明的变量调用方法。
与其他编程语言不同,Ruby不会将变量视为未声明,而是nil
- 使许多开发人员感到困惑。简而言之,错误意味着您试图在没有方法的变量上调用.user
;解决方案是确保声明@image
。
-
错误似乎是由此引起的:
@image.user #-> @image does not exist
因此,您必须检查为什么 @image
尚未声明。
我猜测错误是由routes
引起的。您需要确保正确调用images
控制器:
#config/routes.rb
resources :images
#app/controllers/images_controller.rb
class ImagesController < ApplicationController
def show
@image = Image.find params[:id]
authorize! :read, @image
end
end
这应该只允许拥有该图像的 用户查看它。您不必担心身份验证,因为这将由Devise处理。