Reputation: 13
Moved params permit responsability from model to controller and used comment_attributes instead of comments as @vinodadhikary pointed me
Using better_errors REPL, I traced the problem down to sanitize_for_mass_assignment
method. When doing attributes.permitted?
it returns false
. But doing attributes.permit(:article_id, :name, :email, :body)
returns me exactly que entry parameters!:
>> attributes
=> {"name"=>"Commenter", "email"=>"[email protected]", "body"=>"Here is the comment >> body!! :D"}
>> attributes.permit(:article_id, :name, :email, :body)
=> {"name"=>"Commenter", "email"=>"[email protected]", "body"=>"Here is the comment body!! :D"}
>> attributes.permitted?
=> false
Trying to get in touch with Rails 4, I encountered a problem with (I think) strong parameters use.
I have an Article class which can have many Comments. When creating a new comment doing:
@comment = @article.comments.build(params[:comment])
I get the following error (pointing this line):
ActiveModel::ForbiddenAttributesError at /articles/1/comments
The models are the following:
class Article < ActiveRecord::Base
validates_presence_of :title, :content
validates_uniqueness_of :title
has_many :comments, :dependent => :destroy
accepts_nested_attributes_for :comments
end
Comments:
class Comment < ActiveRecord::Base
belongs_to :article
validates_presence_of :article_id, :author, :body, :content
end
Article controller have this in the private section:
def article_params
params.require(:article).permit(:title, :content, comments_attributes: [:article_id, :name, :email, :body])
end
Comments controller code is:
def create
@article = Article.find(params[:article_id])
@comment = @article.comments.build(params[:comment]) # <--- It fails here
respond_to do |format|
if @comment.save
format.html { redirect_to @comment, notice: 'Comment was successfully created.' }
format.json { render action: 'show', status: :created, location: @comment }
else
format.html { render action: 'new' }
format.json { render json: @comment.errors, status: :unprocessable_entity }
end
end
end
Upvotes: 1
Views: 8363
Reputation: 55
permit params method name should be same as model/controller e.g if model name is "recent_post" then permit method name should be
def recent_post_params .............. end
Upvotes: 0
Reputation: 38645
The methods article_params
and comment_params
that you have in the models belong in their respective controllers not in models. The idea is to filter the parameters passed to the model in the controller rather than in the model. Take a read on http://edgeapi.rubyonrails.org/classes/ActionController/StrongParameters.html, on how to allow attributes for nested attributes.
You models should be as follows:
# Articles.rb
class Article < ActiveRecord::Base
validates_presence_of :title, :content
validates_uniqueness_of :title
has_many :comments, :dependent => :destroy
accepts_nested_attributes_for :comments
end
# Comment.rb
class Comment < ActiveRecord::Base
belongs_to :article
validates_presence_of :article_id, :author, :body, :content
end
Then move the strong parameters to Articles Controller as follows:
#ArticlesController.rb
def create
@article = Article.find(params[:article_id])
@comment = @article.comments.build(params[:comment])
respond_to do |format|
if @comment.save
format.html { redirect_to @comment, notice: 'Comment was successfully created.' }
format.json { render action: 'show', status: :created, location: @comment }
else
format.html { render action: 'new' }
format.json { render json: @comment.errors, status: :unprocessable_entity }
end
end
end
private
def article_params
params.require(:article).permit(:title, :content, comments_attributes: [:article_id, :author, :email, :body, :content])
end
Upvotes: 3