I've started learning Ruby on Rails.
Iam getting below error: ActiveModel::ForbiddenAttributesError in PostsController#create
Here is the code:
posts_controller.rb
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.create(params[:post]) // Its showing me error here
if #post.save
redirect_to posts_path notice: "Your Post was saved"
else
render "new"
end
end
end
new.html.erb
<h1> Add a New Post </h1>
<%= form_for #post do |f| %>
<p>
<%= f.label :title %><b/>
<%= f.text_field :title %><b/>
</p>
<p>
<%= f.label :content %><b/>
<%= f.text_area :content %><b/>
</p>
<%= f.submit "Add a New Post" %>
<% end %>
post.rb
class Post < ActiveRecord::Base
validates_presence_of :title, :content
end
Please tell me what went wrong. BTW, iam using Rails4
In rails4 there is strong parameters so you can't do this:
#post = Post.create(params[:post])
You need
#post = Post.create(post_params)
Where post_params is a method in your controller:
private
def post_params
params.require(:post).permit!
end
permit! will permit anything. You can limit it though to what you want to allow for example params.require(:post).permit(:title, :content)
You have to use strong params for rails 4 to solve this problem.
Docs: http://edgeguides.rubyonrails.org/action_controller_overview.html#strong-parameters
def post_params
params.require(:post).permit(:title, :content)
end
and in create action use: Post.create(post_params)
You have to use strong params always when you create or update a record.
Related
This question already has answers here:
ActiveModel::ForbiddenAttributesError when creating new user
(8 answers)
Closed 6 years ago.
I'm attempting to make a blog post on my web-app updatable from the browser, but when I click update in the edit for, I get this error:
ActiveModel::ForbiddenAttributesError
error in pots_controller line 33:
if #post.update_attributes(params[:post])
this is my edit.html.erb code:
<h1>Edit Post</h1>
<%= form_for #post do |f| %>
<p>
<%= f.label :title %><br />
<%= f.text_field :title %><br />
</p>
<p>
<%= f.label :body %><br />
<%= f.text_field :body %><br />
</p>
<p>
<%= f.select :category_id, Category.all.collect {|x| [x.name, x.id]}, {:include_blank => "Select One"} %><br />
</p>
<p>
<%= f.submit "Update post" %>
</p>
<% end %>
<%= link_to "Go Back", post_path %>
this is my posts_controller.rb code:
class PostsController < ApplicationController
def index
#posts = Post.find(4,5)
end
def show
#post = Post.find(params[:id])
end
def new
#post = Post.new
#category = Category.all
end
def create
#post = Post.new(params[:post])
if #post.save
redirect_to posts_path, :notice => "Your post has been saved"
else
render "new"
end
end
def edit
#post = Post.find(params[:id])
end
def update
#post = Post.find(params[:id])
if #post.update_attributes(params[:post])
redirect_to post_path, :notice => "Your post has been updated"
else
render "edit"
end
end
def destroy
#post = Post.find(params[:id])
#post.destroy
redirect_to posts_path, :notice => "Your post has been deleted"
end
end
hope and thank anyone can help. Best, M
Strong Parameters
Rails uses a security mechanism called Strong Parameters by default. Its purpose is to ensure that only certain fields can be updated via a user submitted form.
#post.update_attributes(params[:post]) is an old-style syntax which does not work with strong parameters.
The updated convention is as follows
class PostsController
def update
# ...
#post.update(post_params) # instead of passing params[:post] directly, you pass it a strong parameters whitelist (see below)
end
def post_params
# we construct a strong parameters whitelist below
# require(:post) means that the `params` hash MUST contain a :post key
# permit(:title, :body, ...) = here we enumerate the attributes which we will accept from the form parameters; it acts as a whitelist
params.require(:post).permit(:title, :body, ...)
end
end
If you use rails g scaffold you can see an example of a controller which uses strong parameters.
DON'T DO THIS: To disable using strong parameters by default, you can set the following config value
config.active_record.whitelist_attributes = false
I included this for completeness' sake, however you should not do this as it will unnecessarily introduce security vulnerabilities to your code.
Additional Resources
ActiveModel::ForbiddenAttributesError when creating new user
http://edgeapi.rubyonrails.org/classes/ActionController/StrongParameters.html
https://github.com/rails/strong_parameters
I'm following a rails tutorial and need some help to proceed further. Problem is, once I fill out the form which has a title,body fields and hit submit, it has to redirect to the show.html.erb page instead it throws an error.
Error: The action 'create' could not be found for PostsController
routes.rb
Rails.application.routes.draw do
get "/pages/about" => "pages#about"
get "/pages/contact" => "pages#contact"
get "/posts" => "posts#index"
post "/posts" => "posts#create"
get "/posts/show" => "posts#show", as: :show
get "/posts/new" => "posts#new"
end
posts_controller_tests.rb
require 'test_helper'
class PostsControllerTest < ActionController::TestCase
def index
end
def new
#post = Post.new
end
def create
#post = Post.new(post_params)
#post.save
redirect_to show_path
end
def show
end
private
def post_params
params.require(:post).permit(:title, :body)
end
end
new.html.erb
<h1>Create a new blog post</h1>
<div class="form">
<%= form_for Post.new do |f| %>
<%= f.label :title %>: <br>
<%= f.text_field :title %> <br> <br>
<%= f.label :body %>: <br>
<%= f.text_area :body %> <br> <br>
<%= f.submit %>
<% end %>
</div>
Any help on this would be appreciated.
Note: You are using posts_controller_tests.rb not posts_controller.rb. You are putting your controller code in test controller.
Try to move the code in app/controllers/posts_controller.rb:
class PostsController < ApplicationController
def index
end
def new
#post = Post.new
end
def create
#post = Post.new(post_params)
#post.save
redirect_to show_path
end
def show
end
private
def post_params
params.require(:post).permit(:title, :body)
end
end
Your create action always redirects you to the show action. It doesn't matter if your model was saved or not.
You have to check if the model was saved or not:
def create
#post = Post.new(post_params)
if #post.save
flash[:success] = 'Successfully saved'
redirect_to #post
else
render 'new'
end
end
If it wasn't saved, it renders the new action again.
Change your routes.rb to this:
Rails.application.routes.draw do
get "/pages/about" => "pages#about"
get "/pages/contact" => "pages#contact"
resources :posts
end
Moreover you should inherit your controller from ActionController::Base
so change first line of your controller to
class PostsController < ActionController::Base
and move the controller to app/controllers/posts_controller.rb
All,
I just created markdown_title and markdown_body methods. When I go to the show view page for my Post model I am getting the error: Wrong number of arguments.
I believe my markdown_title method(also for markdown_body) might be constructed incorrectly below in the post.rb file. Is this the culprit?:
class Post < ActiveRecord::Base
has_many :comments
has_one :summary
belongs_to :user
belongs_to :topic
#has_one :summary
default_scope {order('created_at DESC')}
validates :title, length: {minimum: 5}, presence: true
validates :body, length: {minimum: 20}, presence: true
validates :topic, presence: true
validates :user, presence: true
def markdown_title
(render_as_markdown).render(self.title).html_safe
end
def markdown_body
(render_as_markdown).render(self.body).html_safe
end
private
def render_as_markdown
renderer = Redcarpet::Render::HTML.new
extensions = {fenced_code_blocks: true}
redcarpet = Redcarpet::Markdown.new(renderer, extensions)
#return redcarpet
end
end
Here is my code for my show.html.erb file where the error is appearing while calling my markdown_title method:
<h1><%= #post.markdown_title #post.title %></h1>
<div class="row">
<div class="col-md-8">
<p><%= #post.body %></p>
</div>
<div class="col-md-4">
<% if policy(#post).edit? %>
<%= link_to "Edit", edit_topic_post_path(#topic, #post), class: 'btn btn-success' %>
<% end %>
</div>
</div>
<% if #post.summary.present? %>
<h1>Post Summary</h1>
<p><%= #post.summary.body %></p>
<% else %>
<%= form_for [#topic, #post, #post.build_summary] do |f| %>
<%= f.text_field :body %>
<%= f.submit %>
<% end %>
<% end %>
This is the Post controller:
class PostsController < ApplicationController
#def index #for the index page
##posts = Post.all
#authorize #posts
#end
def show
#post = Post.find(params[:id])
#topic = Topic.find(params[:topic_id])
end
def new
#topic = Topic.find(params[:topic_id])
#post = Post.new
authorize #post #authorize() will check the policy on new post resources
# if user is present it wll let it render if no user present itll give exception
end
def create
##post = Post.new(params.require(:post).permit(:title, :body))
#require and permit make sure only certain keys are passed to Post.new
#topic = Topic.find(params[:topic_id])
##post = current_user.posts.build(params.require(:post).permit(:title, :body))
#post = current_user.posts.build(post_params)
#post.topic = #topic
authorize #post #authorize() will check if user is logged in if not itll give an exception
if #post.save
flash[:notice] = "Your new post was created and saved."
redirect_to [#topic, #post] #takes you to the new post you created
else
flash[:error] = "There was an error saving the post. Please try again."
render :new # it grabs the new.html.erb file and pastes it in the view
end
end
def edit
#topic = Topic.find(params[:topic_id])
#post = Post.find(params[:id])
authorize #post
end
def update
#topic = Topic.find(params[:topic_id])
#post = Post.find(params[:id])
##post_check = current_user.posts.build(post_params)
authorize #post
if #post.update_attributes(post_params)
flash[:notice] = "Post was updated and captured your new update."
redirect_to [#topic, #post]
else
flash[:error] = "There was an error saving the post. Please try again."
render :new
end
end
private
def post_params
params.require(:post).permit(:title, :body)
end
end
Here is the error I get on my view:
You're calling your markdown_title method with a parameter, in this case, #post.title.
<h1><%= #post.markdown_title #post.title %></h1>
In the definition of your Post class, the markdown_title method doesn't take any parameters.
def markdown_title
(render_as_markdown).render(self.title).html_safe
end
That's why you're seeing the Wrong number of arguments (1 for 0) error.
Since you're already referencing self.title in the markdown_title method, there's no reason to pass #post.title to it. Just remove #post.title from where you're calling markdown_title, and you should be good to go.
I am getting following error in console
Unpermitted parameters: post_detail
Unpermitted parameters: post_detail
My post model has
has_many :post_details
accepts_nested_attributes_for :post_details
and my post_detial model has
belongs_to :post
has_attached_file :upload
post.rb and post_detail.rb is my model files
posts_controller is controller
Here is my form
Here is my posts_controller.rb
def create
#post = Post.new(post_params)
#post.build.post_detail
end
private
def post_params
params.require(:post).permit(:title,:post_details => [:upload_file_name,:upload_file_size,:upload_file_content])
end
Edit 1
<%= form_for #post,html: {multipart: true} do |f| %>
<%= f.text_field :title,placeholder: 'title' %>
<%= f.fields_for :post_detail do |uploads| %>
<%= uploads.file_field :upload %>
<% end %>
<%= f.submit 'submit' %>
<% end %>
My post controller
def new
#post = Post.new
#post.post_details.build
end
def create
#post = Post.new(post_params)
if #post.save
#some flash
end
end
private
def post_params
params.require(:post).permit(:title,:post_details_attributes => [:id, :upload_file_name,:upload_file_size,:upload_file_content,:_destroy])
end
Still unpermitted parameters: post_details occurs
You should build the post_details in the new action, and then save the post with all the params (including the post_details_attributes) in the create action.
def new
#post = Post.new
#post.post_details.build
end
def create
#post = Post.new(post_params)
#post.save
end
private
def post_params
params.require(:post).permit(:title,:post_details_attributes => [:id, :upload_file_name,:upload_file_size,:upload_file_content, :_destroy])
end
I'm following the Getting Started tutorial for Rails 4.0.0 located here:
http://guides.rubyonrails.org/getting_started.html
I'm at the point in section 5.7 where I'm supposed to be getting the ActiveModel::ForbiddenAttributes error. Instead, I get this error:
NoMethodError in Posts#show
Showing C:/Rails/blog/app/views/posts/show.html.erb where line #8 raised:
undefined method `text' for nil:NilClass
Extracted source (around line #8):
5
6 <p>
7 <strong>Text:</strong>
8 <%= #post.text %>
9 </p>
Despite this, I believe the posts are being created, since the ids are being incremented each time I submit the form. I am brand new to Rails, and have attempted to exactly follow the instructions.
I'm running Windows 7 x64, with Ruby 1.9.3 and Rails 4.0.0.
Here are some relevant files; please let me know if any other are required.
posts_controller.rb:
class PostsController < ApplicationController
def new
end
def create
#post = Post.new(post_params)
#post.save
redirect_to #post
end
private
def post_params
params.require(:post).permit(:title, :text)
end
def show
#post = Post.find(params[:id])
end
end
show.html.erb:
<p>
<strong>Title:</strong>
<%= #post.title %>
</p>
<p>
<strong>Text:</strong>
<%= #post.text %>
</p>
new.html.erb
<h1>New Post</h1>
<%= form_for :post, url: posts_path do |f| %>
<p>
<%= f.label :title %><br>
<%= f.text_field :title %>
</p>
<p>
<%= f.label :text %><br>
<%= f.text_area :text %>
</p>
<p>
<%= f.submit %>
</p>
<% end %>
Just write down show method after create method, as your show method is below the keyword private it is taking private as a Access Modifier and hence can't access directly through browser
class PostsController < ApplicationController
def new
end
def create
#post = Post.new(post_params)
#post.save
redirect_to #post
end
def show
#post = Post.find(params[:id])
end
private
def post_params
params.require(:post).permit(:title, :text)
end
end
I was having the same problem with the tutorial (which at this date (11/18/14) uses 'articles' instead of 'posts'), and found the solution to be the placement of the following "def" block in articles_controller.rb:
def show
#article = Article.find(params[:id])
end
Here's what it looks like for me:
class ArticlesController < ApplicationController
def new
end
def create
#article = Article.new(article_params)
#article.save
redirect_to #article
end
def show
#article = Article.find(params[:id])
end
private
def article_params
params.require(:article).permit(:title, :text)
end
end