I am using rails 5.0.0. I get the following error when I try to create a reply to a forum post.
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):
This is my part of my replies controller file. The error makes it seem like there something is wrong with the create action so that is what I have included for this post. Also, my schema, there is a 'replies' table with a column named 'reply' which is the actual text the user wants to submit as their response. Sorry for the confusing naming scheme.
I feel like the create action is correct, and that there is something wrong elsewhere. Like a strong parameters type of problem? Are there any suggestions as to where else in my files could cause an error like this to arise?
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
end
The problem is in this line:
@reply = @discussion.replies.create(params[:reply]).permit(:reply, :discussion_id)
You should use something like:
@reply = @discussion.replies.create(reply_params)
I'd suggest you update the form to include discussion_id
, and add this to the reply_params
. That way you can create the record using the line suggested above.
To do this, you'd need a line similar to the below in your form:
<%= f.hidden_field :discussion_id, @discussion.id %>
However, it's worth considering users can still edit this on the page if they have nefarious intentions. Therefore, if it's crucial to security that the discussion is fixed you can handle the assignment server side (as you're actually currently doing - see my update below).
Hope that helps - let me know how you get on / if you have any questions.
Update
As you're using @discussion.replies.create...
the discussion_id
will be assigned automatically. This means the following should just work:
@reply = @discussion.replies.create(reply_params)
Strong params are used to prevent issues stemming from mass assignment, so as you're actually only assigning a single attribute here you could simplify it further still:
@reply = @discussion.replies.create(params[:reply][:reply])
However, I'd recommend the first option as you can simply add new columns to reply_params
as your project scales.
Hope that helps!