【问题标题】:ActiveModel::ForbiddenAttributesError when creating a reply to a forum post创建对论坛帖子的回复时出现 ActiveModel::ForbiddenAttributesError
【发布时间】:2018-03-19 16:17:48
【问题描述】:

我正在使用 Rails 5.0.0。当我尝试创建对论坛帖子的回复时,我收到以下错误。

Started POST "/discussions/7/replies" for 108.252.220.249 at 2018-03-19 15:54:44 +0000
Cannot render console from 108.252.220.249! Allowed networks: 127.0.0.1,::1, 127.0.0.0/127.255.255.255
Processing by RepliesController#create as JS
Parameters: {"utf8"=>"✓", "reply"=>{"reply"=>""}, "commit"=>"Submit Reply", "discussion_id"=>"7"}
User Load (0.6ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? ORDER BY "users"."id" ASC LIMIT ?  [["id", 1], ["LIMIT", 1]]
Discussion Load (0.2ms)  SELECT  "discussions".* FROM "discussions" WHERE "discussions"."id" = ? LIMIT ?  [["id", 7], ["LIMIT", 1]]
(0.1ms)  begin transaction
(0.1ms)  rollback transaction
Completed 401 Unauthorized in 10ms (ActiveRecord: 1.0ms)



ActiveModel::ForbiddenAttributesError (ActiveModel::ForbiddenAttributesError):

这是我的回复控制器文件的一部分。该错误使创建操作看起来有问题,所以这就是我在这篇文章中包含的内容。此外,我的架构有一个“回复”表,其中有一列名为“回复”,这是用户想要提交的实际文本作为他们的回复。对不起,令人困惑的命名方案。

我觉得创建操作是正确的,但其他地方有问题。像强参数类型的问题?对于我的文件中的其他位置可能导致出现此类错误是否有任何建议?

class RepliesController < ApplicationController
before_action :authenticate_user!
before_action :set_reply, only: [:edit, :update, :show, :destroy]
before_action :set_discussion, only: [:create, :edit, :show, :update, :destroy]

def create
    #create a reply within the discussion and save userid to the reply
    @reply = @discussion.replies.create(params[:reply]).permit(:reply, :discussion_id)
    @reply.user_id = current_user.id

    respond_to do |format|
        if @reply.save
            format.html {redirect_to discussion_path(@discussion)}
            format.js #render create.js.erb

        else
            format.html{redirect_to discussion_path(@discussion), notice: 'Reply did not save. Try again'}
            format.js
        end
    end
end

...

private
def set_discussion
    @discussion = Discussion.find(params[:discussion_id])
end

def set_reply
    @reply = Reply.find(params[:id])
end

def reply_params
    params.require(:reply).permit(:reply)
end

结束

【问题讨论】:

    标签: ruby-on-rails ruby web model-view-controller forum


    【解决方案1】:

    问题出在这一行:

     @reply = @discussion.replies.create(params[:reply]).permit(:reply, :discussion_id)
    

    你应该使用类似的东西:

     @reply = @discussion.replies.create(reply_params)
    

    我建议您更新表单以包含discussion_id,并将其添加到reply_params。这样您就可以使用上面建议的行创建记录。

    为此,您需要在表单中添加类似于以下内容的行:

    <%= f.hidden_field :discussion_id, @discussion.id %>
    

    但是,值得考虑的是,如果用户有恶意,他们仍然可以在页面上编辑此内容。因此,如果修复讨论对安全性至关重要,您可以处理分配服务器端(正如您目前正在做的那样 - 请参阅下面的更新)。

    希望对您有所帮助 - 如果您有任何问题,请告诉我您的进展情况。


    更新

    当您使用@discussion.replies.create... 时,将自动分配discussion_id。这意味着以下应该可以正常工作:

    @reply = @discussion.replies.create(reply_params)
    

    强参数用于防止因批量分配引起的问题,因此您实际上只在这里分配了一个属性,您可以进一步简化它:

    @reply = @discussion.replies.create(params[:reply][:reply])
    

    但是,我建议您使用第一个选项,因为随着项目的扩展,您只需将新列添加到 reply_params

    希望有帮助!

    【讨论】:

    • 您好,非常感谢您的回复!您能否提供更多有关更新表单以包含 f.discussion_id 的详细信息?如何将其添加到表单中,这样它实际上不会要求用户在字段中选择某些内容?
    • 当然——一个简单的方法是在表单中使用隐藏字段,例如f.hidden_field :discussion_id, @discussion.id。值得考虑的是,如果用户有恶意,他们仍然可以在页面上进行编辑。因此,如果修复讨论对安全至关重要,您可以处理分配服务器端 - 我现在将使用此选项更新答案:)
    • 事实上,忽略我 - 因为您使用的是@discussion.replies.create...,所以discussion_id 将被自动分配。查看另一个更新。
    • @Nat - 这有帮助吗?
    • 抱歉回复晚了。直到最近我才有机会测试您的解决方案。但是,是的,您在更新版本中的解决方案似乎效果很好!感谢您抽出宝贵时间回复和检查。现在我也知道如何在表单中添加隐藏字段了。如此伟大而有益的回应。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-06-24
    • 2016-12-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多