NoMethodError:nil:NilClass 的未定义方法“销毁”

问题描述 投票:0回答:1

我正在尝试创建一个用于学习 Ruby On Rails 的迷你博客。

我使用 Devise-token-auth gem 进行身份验证,使用 Pundit gem 进行权限。我使用资源方法分层组织项目

当我尝试删除帖子时,没有任何反应。更新工作正常......

当我尝试调试时,错误 NoMethodError: undefined method `destroy' for nil:NilClass 当我将代码行 authorize Posts::Destroy.new(@post).execute 放在控制台时出现

我研究了很多但找不到解决方案,你能帮我吗?

这些是我的代码

class Posts::Destroy
  attr_accessor :post

  def initialize(post)
    @post = post
  end

  def execute
    post.destroy
  end
end
class PostsController < ApplicationController
  before_action :set_post, only: %i[show update destroy]
  before_action :authenticate_user!, except: :index

  def index
    posts = Posts::List.new(params).execute

    render json: posts, meta: pagination(posts), each_serializer: PostSerializer, status: :ok
  end

  def show
    render json: @post, serializer: PostSerializer, list_comments: true, status: :ok
  end

  def create
    @post = authorize Posts::Create.new(post_params).execute

    render json: @post, serializer: PostSerializer, status: :created
  end

  def update
    authorize @post
    Posts::Update.new(post_params, @post).execute
    render json: @post, serializer: PostSerializer, status: :ok
  end

  def destroy
    authorize Posts::Destroy.new(@post).execute
    format.json { head :no_content }
  end

  private

  # Use callbacks to share common setup or constraints between actions.
  def set_post
    authorize @post = Post.find(params[:id])
  end

  # Only allow a list of trusted parameters through.
  def post_params
    params.require(:post).permit(:title, :description, :category_id, :user_id)
  end
end
class PostPolicy < ApplicationPolicy
  def new?
    user_is_owner_of_record?
  end

  def index?
    true
  end

  def show?
    true
  end

  def create?
    user.present? && (user&.admin || user_is_owner_of_record?)
  end

  def update?
    user.present? && (user&.admin || user_is_owner_of_record?)
  end

  def destroy?
    user.present? && (user&.admin || user_is_owner_of_record?)
  end

  def user_is_owner_of_record?
    @user == @record.user
  end
end

class ApplicationController < ActionController::Base
  include DeviseTokenAuth::Concerns::SetUserByToken
  include ErrorsHandler::Handler
  include ActionController::MimeResponds
  include ActionController::Serialization
  include Pundit::Authorization

  protect_from_forgery with: :null_session

  prepend_before_action :configure_permitted_parameters, if: :devise_controller?

  after_action :verify_authorized, except: :index, unless: :devise_controller?

  rescue_from Pundit::NotAuthorizedError, with: :user_not_authorized

  around_action :switch_locale

  private

  def switch_locale(&action)
    locale = params[:locale] || I18n.default_locale
    I18n.with_locale(locale, &action)
  end

  def default_url_options
    { locale: I18n.locale }
  end

  def user_not_authorized
    flash[:alert] = 'You are not authorized to perform this action.'
    redirect_back(fallback_location: root_path)
  end

  def configure_permitted_parameters
    devise_parameter_sanitizer.permit(:account_update, keys: %i[name username])
    devise_parameter_sanitizer.permit(:sing_up, keys: %i[password email name username])
  end

  def pagination(object)
    {
      current_page: object.current_page,
      per_page: object.per_page(params),
      total_pages: object.total_pages,
      total_count: object.total_count
    }
  end
end

我相信是时候授权当前用户没有被传递

我只检查了controller里面有没有set_post,不知道还要测试什么

希望能正常删帖

undefined ruby-on-rails-7 nomethoderror ruby-2.7
1个回答
0
投票

欢迎来到SO!

  def destroy
    authorize Posts::Destroy.new(@post).execute
    format.json { head :no_content }
  end

authorize
正在尝试根据
Posts::Destroy.new(@post).execute

返回的内容采取行动
  def execute
    post.destroy
  end

那么返回的是什么? 根据文档

#delete

删除数据库中的记录并冻结此实例以反映不应进行任何更改(因为它们无法持久化)。

所以它返回一个内存中的

post
实例,但是你不能在它上面调用任何依赖数据库的方法,因为它只存在于内存中。

  def destroy?
    user.present? && (user&.admin || user_is_owner_of_record?)
  end

  def user_is_owner_of_record?
    @user == @record.user
  end

这就是我们发现问题的地方:

@record.user
是一个数据库调用,它试图查找关联的
user
记录。但是
@record
已经不存在于数据库中,所以调用失败。

你有两个选择:

  1. authorize
    在你之前
    #destroy
  def destroy
    authorize @post
    Posts::Destroy.new(@post).execute
    format.json { head :no_content }
  end
  1. 从您的
    #user_is_owner_of_record?
    调用中删除数据库调用:
  def destroy?
    user.present? && (user&.admin || user_is_owner_of_record?)
  end

  def user_is_owner_of_record?
    @user.id == @record.user_id
  end
© www.soinside.com 2019 - 2024. All rights reserved.