gpt4 book ai didi

ruby-on-rails - Pundit 策略错误未定义方法 `image' 为 nil :NilClass

转载 作者:行者123 更新时间:2023-12-04 03:16:45 24 4
gpt4 key购买 nike

我已经被这个问题困扰了很长一段时间,不确定我做错了什么。

我正在使用 Rails 4.2.5.1、Pundit 1.1.0 和 Devise。

我有一篇博客文章显示以下内容:

  • 标题
  • 作者用户名
  • 图片
  • 经过过滤的摘录(在索引页上)
  • 正文(在显示页面上)

索引页面显示正确(除了不显示的作者用户名,因为它不识别用户名参数)。但是,当我尝试通过显示页面查看单个帖子时,出现以下错误:

undefined method `image' for nil:NilClass

如果我删除用于显示图像的那行代码,我会收到标题错误以及相同的未定义方法错误。

我已按照 SitePoint-source/Authorization_with_Pundit 中的示例进行操作几乎完全适用于策略和 Controller (仅进行少量修改)

在添加 Pundit 以在管理员、编辑和用户之间创建授权之前,一切都运行良好。

这是我当前的代码:

应用程序 Controller

class ApplicationController < ActionController::Base
include Pundit
rescue_from Pundit::NotAuthorizedError, with: :user_not_authorized

# Prevent CSRF attacks by raising an exception.
# For APIs, you may want to use :null_session instead.
protect_from_forgery with: :exception
before_filter :configure_permitted_parameters, if: :devise_controller?

private

def user_not_authorized
flash[:alert] = "Access denied. You are not authorized to view that page."
redirect_to (request.referrer || root_path)
end


protected

def configure_permitted_parameters
devise_parameter_sanitizer.permit(:sign_up) { |u| u.permit(:username, :email, :password, :password_confirmation, :remember_me) }
devise_parameter_sanitizer.permit(:sign_in) { |u| u.permit(:username, :email, :password, :remember_me) }
devise_parameter_sanitizer.permit(:account_update) {|u| u.permit(:username, :email, :password, :password_confirmation, :current_password)}
end


end

后 Controller

class PostsController < ApplicationController
before_action :set_post, only: [:show, :edit, :update, :destroy]
after_action :verify_authorized, only: [:destroy]
after_action :verify_policy_scoped, only: [:user_posts]

def index
@meta_title = "Blog"
@meta_description = "description here"
@posts = Post.all.order("created_at DESC").paginate(:page => params[:page], :per_page => 4)
end

def show
end

def new
@meta_title = "Add New Blog"
@meta_description ="Add a new blog to your profile."
@post = Post.new
end

def edit
@meta_title = "Edit Blog"
@meta_description ="Edit an existing blog from your profile."
end

def create
@post = Post.new
@post.update_attributes(permitted_attributes(@post))

if @post.save
redirect_to @post, notice: 'Post was successfully created.'
else
render :new
end
end

def update

@post = Post.find(params[:id])
if @post.update_attributes(permitted_attributes(@post))
redirect_to @post, notice: 'Post was successfully updated.'
else
render :edit
end
end

def destroy
if @post.present?
authorize @post
@post.destroy
else
skip_authorization
end

redirect_to posts_url, notice: 'Post was successfully deleted.'
end

def user_posts
@posts = policy_scope(Post)
end

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

# Only allow the white list through.
def post_params
params.require(:post).permit(policy(@post).permitted_attributes)
end
end

申请政策

class ApplicationPolicy
attr_reader :user, :record

def initialize(user, record)
raise Pundit::NotAuthorizedError, "You must be logged in to perform this action" unless user
@user = user
@record = record
end

def index?
false
end

def show?
scope.where(:id => record.id).exists?
end

def create?
false
end

def new?
create?
end

def update?
false
end

def edit?
update?
end

def destroy?
false
end

def scope
Pundit.policy_scope!(user, record.class)
end

class Scope
attr_reader :user, :scope

def initialize(user, scope)
@user = user
@scope = scope
end

def resolve
scope
end
end
end

发布政策

class PostPolicy < ApplicationPolicy
class Scope < Scope
def resolve
scope.where(user: user)
end
end

def permitted_attributes
if user.admin? || user.editor?
[:title, :body, :image, :permalink, :description, :tag_list, :username]
else
[:title, :body, :image, :username]
end
end

def new?
user.admin? || user.editor?
end

def index?
true
end

def create?
user.admin? || user.editor?
end

def update?
user.admin? || user.editor? || record.user == user
end

def destroy?
user.admin? || record.user == user
end
end

Post.rb

class Post < ActiveRecord::Base
include ActiveModel::ForbiddenAttributesProtection
belongs_to :user

# This method associates the attribute ":image" with a file attachment
has_attached_file :image, styles: {
thumb: '100x100>',
square: '200x200#',
medium: '300x300>',
}

extend FriendlyId
friendly_id :permalink, use: [:slugged, :history, :finders]
validates :permalink, presence: true, uniqueness: true
validates :title, presence: true, length: { minimum: 5}
validates :description, presence: true, uniqueness: true, length: {maximum: 160}
validates :body, presence: true
validates :image, presence: true
# Validate the attached image is image/jpg, image/png, etc
validates_attachment_content_type :image, :content_type => /\Aimage\/.*\Z/

def should_generate_new_friendly_id?
permalink_changed?
end
end

发布#show

<% provide(:title, "@post.title") %>
<% provide(:description, "@post.description") %>

<div class="row">
<div class="col-md-offset-1 col-md-10">
<div class="panel panel-default">
<div class="panel-heading center">
<%= image_tag @post.image.url, :style => "width: 100%; height: auto;" %>
</div>
<div class="panel-body">
<h2 class="title center"><%= @post.title %></h2>
<p class="posted"><i class="ion-android-time"></i> <%= @post.created_at.strftime("%B %d, %Y") %> </p>
<p class="posted"><i class="ion-person"></i> Author: <%= link_to @post.username, about_path(:anchor => "coaches") %></p>
<hr>
<div class="postBody" id="summernote">
<%= @post.body.html_safe %>
</div>
</div>
<div class="panel-footer center">
<%= link_to 'Back', posts_path %> |
<%= link_to 'Edit', edit_post_path(@post) %> |
<%= link_to 'Delete', @post, method: :delete, data: { confirm: 'Are you sure you want to delete this post?' } %>
<%= render 'disqus' %>
</div>
<div class="panel-footer center">
<%= link_to 'Back', posts_path %>
</div>
</div>
</div>
</div>

发布#index

<div class="container">
<div class="row">
<div class="col-md-9">
<% @posts.each do |post| %>
<div class="post-wrapper">
<h3 class="title center"><%= link_to post.title, post %></h3>
<p class="posted"><i class="ion-android-time"></i> <%= post.created_at.strftime("%B %d, %Y") %></p>
<p class="posted"><i class="ion-person"></i> Author: <%= link_to post.user(:username), about_path(:anchor => "coaches") %></p><br>
<div class="post-image center"><%= link_to image_tag(post.image.url, :style => "width: 100%; height: auto;"), post %></div><br>

<%= sanitize(post.body[0,300]) %>...<br>
<div class="center">
<%= link_to 'View Blog', post, class: "btn btn-primary" %>
<% if policy(post).update? %>
<%= link_to 'Edit', edit_post_path(post) %> |
<% end %>
<% if policy(post).destroy? %>
<%= link_to 'Delete', post, method: :delete, data: { confirm: 'Are you sure?' } %>
<% end %>
</div>
<br>
</div>
<% end %>
<div class="center">
<%= will_paginate @posts, renderer: BootstrapPagination::Rails %>
</div>
</div>
</div>
</div>

我还有一些其他问题,希望在解决此问题后自行解决:

  • 已删除的帖子会收到一条提示消息说它们已删除,但它们仍然存在
  • 编辑帖子收到相同的图片错误消息
  • 未登录的用户无法查看帖子,我希望他们能够查看所有帖子,无论是否登录。这是同一个问题,但该解决方案对我不起作用,我没有收到任何类型的 Rails 错误消息:Pundit policy_scope error .也许这与 App Policy 中的初始化有关?

这些其他问题可以稍后解决,或者如果您看到错误,我将不胜感激。

现在我的主要问题是尝试解决 undefined method "image"for nil:NilClass 错误

最佳答案

undefined method `image' for nil:NilClass

这意味着您要调用的对象 .image on (即 @post )是 nil .追溯过去,找出为什么它是零。

在你的Posts#show查看,您依赖于 set_post回调来设置你的帖子。 set_post回调使用 Post.find_byid查找记录的参数。

方式find_by行为是返回 nil如果它给出的参数是 nil (即如果你调用 Post.find_by(id: nil) ,你会得到 nil 回来)。这可能表明 params[:id]本身就是nil - 检查它是否设置为查询字符串参数 ( example.com/posts/show?<i><b>id=12</b></i> ) 或 URL 本身的一部分 ( example.com/posts/<i><b>12</b></i> )。

如果你分不清,加一个byebug调用你的Posts#show Action :

def show
byebug
end

这将在执行时停止操作,并为您提供一个控制台 - 此时,您可以键入 params[:id]找出它的值(value)是什么。

我建议不要使用 Post.find_by , 你使用 Post.find .不同之处在于 find默认使用 ID(所以你不需要指定你使用的参数),它会引发 404 Not Found 响应而不是返回 nil如果找不到记录。为此,您的 set_post回调应该是这样的:

def set_post
@post = Post.find params[:id]
end

关于ruby-on-rails - Pundit 策略错误未定义方法 `image' 为 nil :NilClass,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40366644/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com