ActiveModel::ForbiddenAttributesError - ruby-on-rails

i've been following rails guide on creating and mounting an engine here.Created blog post and when i tried to comment ,it returned "ActiveModel::ForbiddenAttributesError in Blorgh::CommentsController#create " error.
Comment controller
require_dependency "blorgh/application_controller"
module Blorgh
class CommentsController < ApplicationController
def create
#post = Post.find(params[:post_id])
#comment = #post.comments.create(params[:comment])
flash[:notice] = "Comment has been created!"
redirect_to posts_path
end
end
end
and here is comment model
module Blorgh
class Comment < ActiveRecord::Base
end
end
how to resolve the issue?

I guess you are using rails 4. You need to mark all the required parameters
here it goes :
def create
#post = Post.find(params[:post_id])
#comment = #post.comments.create(post_params)
flash[:notice] = "Comment has been created!"
redirect_to posts_path
end
def post_params
params.require(:blorgh).permit(:comment)
end
hope this link helps...

I had the same error. So if you disect the params hash it easy to see the nested comment params with text key. Seems the tutorial is for Rails 3, so for the rails 4 way with trusted params the changes needed is to add the comment_params method as below.
Parameters:
{"utf8"=>"✓",
"authenticity_token"=>"uOCbFaF4MMAHkaxjZTtinRIOlpMj2QSOYf+Ugn5EMUI=",
"comment"=>{"text"=>"asfsadf"},
"commit"=>"Create Comment",
"post_id"=>"1"}
def create
#post = Post.find(params[:post_id])
#comment = #post.comments.create(comment_params)
flash[:notice] = "Comment has been created!"
redirect_to posts_path
end
private
# Only allow a trusted parameter "white list" through.
def comment_params
params.require(:comment).permit(:text)
end

Related

ActionController::ActionControllerError in CommentsController#create

Following is the controller
class CommentsController < InheritedResources::Base
def comment_params
params.require(:comment).permit(:name, :email, :body, :post_id)
end
def create
#comment = Comment.new(params[:comment_params])
if #comment.save
flash[:notice] = 'Comment was succesfully posted.'
redirect_to(#comment.post)
else
flash[:notice] = "Error creating comments: #{#comment.errors}"
redirect_to(#comment.post)
end
end
end
All I see is,
ActionController::ActionControllerError in CommentsController#create
Cannot redirect to nil!
Rails.root: c:/sites/myrubyblog
Application Trace | Framework Trace | Full Trace
app/controllers/comments_controller.rb:13:in `create'
By commenting the redirect_to in else block will through a different error saying missing template!
did try the few solutions from previously asked questions, but nothing is helping!
In your else block are also redirecting to #comment.post even though it's not saved. So basically it is nil.
I don't think your comment is being saved. Try doing this to find out if there is any error
if #comment.save! # this will show errors if any
...
else
post = Post.find(params[:post_id])
redirect_to post
end
I am assuming your params has post_id in it. If not #comment.post will also be nil. Causing that error in both if and else blocks.
not params[:comment_params] but comment_params, you should change your create action to this and ensure your post_id is set:
class CommentsController < InheritedResources::Base
def comment_params
params.require(:comment).permit(:name, :email, :body, :post_id)
end
def create
#comment = Comment.new(comment_params)
if #comment.save
flash[:notice] = 'Comment was succesfully posted.'
redirect_to(#comment.post)
else
flash[:notice] = "Error creating comments: #{#comment.errors}"
redirect_to(#comment.post)
end
end
end
else
flash[:notice] = "Error creating comments: #{#comment.errors}"
redirect_to(#comment.post) <--
end
When it failed to save, it tries to redirect to #comment.post, but it's nil because you didn't set post_id correctly
#comment = Comment.new(params[:comment_params])
Which should be
#comment = Comment.new(comment_params)

Fat Model, Skinny Controller in Rails with example

I really want to start learning Rails best practices, especially following the "fat model, skinny controller" logic.
Say I have the following comment controller
class CommentsController < ApplicationController
def create
#post = Post.find(params[:post_id])
#comment = #post.comments.create(comment_params)
#comment.user_id = current_user.id if current_user
#comment.save!
if #comment.save
redirect_to post_path(#post)
else
render 'new'
end
end
def edit
#post = Post.find(params[:post_id])
#comment = #post.comments.find(params[:id])
end
def update
#post = Post.find(params[:post_id])
#comment = #post.comments.find(params[:id])
if #comment.update(params[:comment].permit(:comment))
redirect_to post_path(#post)
else
render 'Edit'
end
end
def destroy
#post = Post.find(params[:post_id])
#comment = #post.comments.find(params[:id])
#comment.destroy
redirect_to post_path(#post)
end
private
def comment_params
params.require(:comment).permit(:comment)
end
What's a good place to start refactoring the code?
Immediately I think I an make the #post and #comment in both edit and update into a separate method, follow by calling a before_action on the method. But that is still putting all the code in the controller.
Are there any code that I can move to the model? If so, how should I structure them?
This code doesn't have much room for improvement, it's a basic crud, here's an example of a before_action like you suggested
before_action :load_post_and_comment, only: %i(edit update destroy)
def load_post_and_comment
#post = Post.find(params[:post_id])
#comment = #post.comments.find(params[:id])
end
And here a couple of other notes
def create
# ...
#comment.save!
if #comment.save
# ...
else
# ..
end
end
In this codition the you should remove the extra #comment.save! you only need to save once.
def update
# ...
if #comment.update(params[:comment].permit(:comment))
# ...
else
# ...
end
end
You already have the comment_params method, use it, because if you at any point add a new attribute to the comment, you'll update that method but you'll probably forget this part and you'll get werid errors till you notice that you need to permit here too.
If you want to really go all out with the skinny controller model, there is this gem: https://github.com/NullVoxPopuli/skinny_controllers
Where, you'd configure your CommentsController like so:
class CommentsController < ApplicationController
include SkinnyControllers::Diet
def create
if model.errors.present?
render 'new'
else
redirect_to post_path(model)
end
end
def update
redirect_to post_path(model)
end
# ... etc
private
def comment_params
params.require(:comment).permit(:comment)
end
end

Updating Rails 4 code to Rails 4.2 code

I'm working through the Apress "Beginning Rails 4, 3rd edition" book. The book introduces you to Rails by building a blog application step by step. I'm about halfway through, and have received the following error message:
ActiveModel::ForbiddenAttributesError in CommentsController#create
I've traced this to my comments_controller.rb file, which looks like this:
class CommentsController < ApplicationController
before_filter :load_article
def create
#comment = #article.comments.new(params[:comment])
if #comment.save
redirect_to #article, :notice => 'Thanks for your comment'
else
redirect_to #article, :alert => 'Unable to add comment'
end
end
def destroy
#comment = #article.comments.find(params[:id])
#comment.destroy
redirect_to #article, :notice => 'Comment deleted'
end
private
def load_article
#article = Article.find(params[:article_id])
end
end
Specifically, the problem seems to be caused by line 5:
#comment = #article.comments.new(params[:comment])
From what I've gathered, the problem seems to be that the book I'm working through was written for an earlier version of Rails. I'm using Rails 4.2.0, and it seems that I ned to use different syntax. What do I need to change to get my code to work?
You need a method that's private in your controller called comment_params (convention, you could call it anything)
Controller:
def create
#comment = #article.comments.new(comment_params)
if #comment.save
redirect_to #article, :notice => 'Thanks for your comment'
else
redirect_to #article, :alert => 'Unable to add comment'
end
end
private
def comment_params
params.require(:comment).permit!
end
It's called strong_parameters and is a gem so you can google it to find it on github
params.require(:comment).permit! will permit anything though, you will probably want to limit it by passing attributes params.require(:comment).permit(:name, :message) - assuming you have name and message attributes.
You'll want to replace params[:comment] with the call to the comment_params method in your update method if you have one.
you need to do this before you create your model object. Rails has to sanitize the parameters before you are allowed to put it in there.
comment_params = params.require(:comments).permit(:attribute1, :attribute2)
#comment = #article.comments.new(comment_params)
Under the method load_article add the following method:
def comment_params
params.require(:comment).permit( ... )
end
and replace the three dots with the attributes you need to allow.
Then in your create function you can write
#comment = #article.comments.new(comment_params)
You will probably need to do something similar in your update function.

ActiveModel::ForbiddenAttributesError while creating a new entry

I am new to Ruby on Rails and I was trying to create a simple app when I ended up having a ActiveModel::ForbiddenAttributesError
class PostsController < ApplicationController
def index
#posts = Post.all
end
def show
#post = Post.find(params[:id])
end
def new
#post =Post.new
end
def create
#post = Post.new(params[:post])
if #post.save
redirect_to post_path,:notice=>"success"
else
render "new"
end
end
def edit
end
def update
end
def destroy
end
private
def post_params
params.require(:post).permit(:Title, :content)
end
end
I have seen a similar error here but the solution for that did not fix my issue.
My version of rails is 4.2.0.
The error displayed is
You can't use that params[:post] hash (or any params[*] hash) directly in any mass-assignment method, you need to use a permit call so Rails knows you've checked it and to allow it.
So, change your Post.new to #post = Post.new(post_params)
Change #post = Post.new(params[:post]) to #post = Post.new(post_params).
I think that
def create
#post = Post.new post_params
if #post.save
flash[:success] = "Created new post"
redirect_to #post
else
render 'new'
end
end
def create
#post = Post.new(posts_params)
if #post.save
redirect_to post_path,:notice=>"success"
else
render "new"
end
end
private
def posts_params
params.require(:post).permit(:Title, :content)
end

Ruby on rails 4 attr_accessible

I am trying to access the database and enter some info. it gives me an error saying "undefined local variable or method `post_params' for #< PostsController:0x00000005aad728>"
i know this has been answered here.
but i tried following what they did, and it just does not work, can someone help me with this?
class PostsController < ApplicationController
def index
#post = Post.all
end
def show
#post = Post.find(params[:id])
end
def new
#post = Post.new
end
def create
#post = Post.new(post_params)
if #post.save
redirect_to posts_path, :notice => "Your post was saved"
else
render ="new"
end
private
def post_params
params.require(:post).permit(:title, :content)
end
end
end
Your end for create method is enclosing the private keyword and post_params method. Update it as:
def create
#post = Post.new(post_params)
if #post.save
redirect_to posts_path, :notice => "Your post was saved"
else
render ="new"
end
end # Add end here
private
def post_params
params.require(:post).permit(:title, :content)
end
end # Remove this end
You define your post_params method inside of create method. Move it outside of it and all will be working.

Resources