I am following a guide to build a blog with rails, simple Post model with title and body.
I am using simple form and upon form submission to create a new post, the post saves created_at and updated_at values, but not the actual content submitted in the form.
I have attempted removing the code for simple form and using Rails native form_for. This DOES save all values to the database. I am new to simple form, not certain whether or not I am using it correctly.
Here is the console record:
Started POST "/posts" for ::1 at 2019-08-17 13:51:01 -0500
Processing by PostsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"qY8kYZxVIMBL8lzHYuQ4qOu6nXsTGLWCRhLPJ2eiAU8EyzR61fZppAFBYmgcm3rx02FYAHcCgFBVlUyDTLtDGA==", "post"=>{"title"=>"Simple Form Test", "body"=>"<p>Test Test Test</p>\r\n"}, "commit"=>"Create Post"}
(0.0ms) begin transaction
SQL (3.3ms) INSERT INTO "posts" ("created_at", "updated_at") VALUES (?, ?) [["created_at", "2019-08-17 18:51:01.325736"], ["updated_at", "2019- 08-17 18:51:01.325736"]]
(7.7ms) commit transaction
Redirected to http://localhost:3000/posts/3
Completed 302 Found in 28ms (ActiveRecord: 11.1ms)
Here is the form:
<%= simple_form_for #post do |f| %>
<% if #post.errors.any? %>
<div id="error_explanation">
<h2>
<%= "#{pluralize(#post.errors.count, "error")} prohibited this post from being saved:" %>
</h2>
<ul>
<% #post.errors.full_messages.each do |msg| %>
<li>
<%= msg %>
</li>
<% end %>
</ul>
</div>
<% end %>
<div class="form-group">
<%= f.input :title, class: "form-control" %>
</div>
<div class="form-group">
<%= f.input :body, :as => :ckeditor, input_html: {:ckeditor => {:toolbar => 'FULL'}}, class: "form-control" %>
</div>
<div class="form-group">
<%= f.button :submit %>
</div>
<% end %>
Here is the controller:
class PostsController < ApplicationController
before_action :find_post, only: [:edit, :update, :show, :delete]
# Index action to render all posts
def index
#posts = Post.all
end
# New action for creating post
def new
#post = Post.new
end
# Create action saves the post into database
def create
#post = Post.new
if #post.save(post_params)
flash[:notice] = "Successfully created post!"
redirect_to post_path(#post)
else
flash[:alert] = "Error creating new post!"
render :new
end
end
# Edit action retrives the post and renders the edit page
def edit
end
# Update action updates the post with the new information
def update
if #post.update_attributes(post_params)
flash[:notice] = "Successfully updated post!"
redirect_to post_path(#post)
else
flash[:alert] = "Error updating post!"
render :edit
end
end
# The show action renders the individual post after retrieving the the id
def show
end
# The destroy action removes the post permanently from the database
def destroy
if #post.destroy
flash[:notice] = "Successfully deleted post!"
redirect_to posts_path
else
flash[:alert] = "Error updating post!"
end
end
private
def post_params
params.require(:post).permit(:title, :body)
end
def find_post
#post = Post.find(params[:id])
end
end
Hopin
g to be able to create posts with body and title, and learn more about simple form.
Thanks in advance!
You wrote #post = Post.new without pass your parameters to your object, so when you save you object you save an empty object.
It should be either :
#post = Post.new(post_params)
Or directly
#post = Post.create(post_params)
Related
I'm running into a problem when trying to create a new object using nested resources in Rails. My routing is set up as:
resources :coins do
resources :questions
end
When I attempt to create a new question, it does not save. I'm redirected to the 'questions' page and the form from the 'new' page including everything that was typed into it remains on the page (rather than the list of questions that are supposed to be there when it saves). My controller is as follows:
class QuestionsController < ApplicationController
before_action :find_question, only: [:show]
before_action :find_coin
before_action :authenticate_user!, except: [:index, :show]
def index
#questions = Question.where(coin_id: #coin.id).order("created_at DESC")
end
def show
end
def new
#coin
#question = current_user.questions.build
end
def create
#question = current_user.questions.build(question_params)
if #question.save
redirect_to coin_question(#question.coin_id, #question.id)
else
render 'new'
end
end
private
def find_question
#question = Question.find(params[:id])
end
def find_coin
#coin = Coin.find(params[:coin_id])
end
def question_params
params.require(:question).permit(:content, :ques_num, :coin_id)
end
end
My 'new' page then displays the following form:
<%= simple_form_for #question, url: coin_questions_path(#coin.id) do |f| %>
<%= f.input :ques_num %>
<%= f.input :content %>
<%= f.submit "Post", class: "btn btn-primary" %>
<% end %>
This is my first time using nested resources and its tripping me up a little bit. I really appreciate any assistance here.
Your create action is failing and so it's executing the else statement which is just rendering back your form with the data you entered. The easiest thing to do is to just check out the log file and see why the save it being blocked.
go to /log/development.log and if you're using a mac press Command and the down arrow which will bring you all the way to the bottom of the file.
Also you may want to check out your model validations. If you don't have flash setup or aren't outputting the errors to your view a validation may be causing the form not to save and you wouldn't see the errors.
you could add some error handling to your view like this
<%= form_with(model: question, local: true) do |form| %>
<% if question.errors.any? %>
<div id="error_explanation">
<h2 class="text-danger"><%= pluralize(question.errors.count, "error") %> prohibited this question from being saved:</h2>
<ul class="text-danger">
<% question.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
for your controller try
def create
#question = Question.new(question_params)
if #question.save
flash[:success] = "question created successfully!"
redirect_to question_url(#question.id)
else
render 'new'
end
end
I think there will be error to create question.
if #question.save
redirect_to coin_question(#question.coin_id, #question.id)
else
render 'new'
end
So if record have any error to save it will redirect to new form.
Just use following code to know what is the errors to creating question
def create
#question = current_user.questions.build(question_params)
if #question.save
flash[:notice] = 'Question created'
redirect_to coin_question(#question.coin_id, #question.id)
else
flash[:notice] = 'Some error here!'
render 'new'
end
end
You need to setup flash to show flash error.
I am fairly new to Ruby. I am trying to follow along with a tutorial for creating a simple posting app.
My create action will not work. I tried this and it seems to do something in the terminal, but it doesn't add it to my Posts object.
Here is my posts controller:
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(:title => params[:title], :content => params[:content])
#post.save
end
def edit
end
def update
end
def destroy
end
end
Here is my new view:
<h1>Add a New Post</h1>
<%= form_for #post do |f| %>
<p>
<%= f.label :title %>
<%= f.text_field :title %>
</p>
<p>
<%= f.label :content %>
<%= f.text_area :content %>
</p>
<p>
<%= f.submit "Add a New Post" %>
</p>
<% end %>
This is what comes up in the terminal when I try to submit:
Started POST "/posts" for ::1 at 2016-08-31 17:54:39 -0700
ActiveRecord::SchemaMigration Load (16.4ms) SELECT "schema_migrations".* FROM "schema_migrations"
Processing by PostsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"tGpevHtpEoP5jHYqCn1G7tUKX9YWnx+PWkqlPzKadTCiIEX1UGs96mSCrDf UIShKjp+ObwNA6G1nh3KE5gAIgw==", "post"=>{"title"=>"Jack's Post", "content"=>"Please use this post"}, "commit"=>"Add a New Post"}
(0.1ms) begin transaction
SQL (16.0ms) INSERT INTO "posts" ("created_at", "updated_at") VALUES (?, ?) [["created_at", 2016-09-01 00:54:40 UTC], ["updated_at", 2016-09-01 00:54:40 UTC]]
(14.7ms) commit transaction
No template found for PostsController#create, rendering head :no_content
Completed 204 No Content in 114ms (ActiveRecord: 31.3ms)
I feel like I've read about a million stack overflow posts about this and no one seems to have the answer. Any help would be very appreciated!
You've successfully inserted a record into the database. What do you want to happen next? How about:
redirect_to action: 'index'
You should use strong params to get the parameters you need from the form.
class PostsController < ApplicationController
def create
#post = Post.new(post_params)
#post.save
end
private
def post_params
params.require(:post).permit(:title, :content)
# params.require(:post).permit! # Allow all
end
end
If you want your exisiting solution to work, you would need to prefix the params like this:
#post = Post.new(:title => params[:post][:title], :content => params[:post][:content])
If you examine the logs, you'll see the form input is nested inside of post
"post"=>{"title"=>"Jack's Post", "content"=>"Please use this post"}
When you look in the logs it clearly says that I have rendered no view.
No template found for PostsController#create, rendering head :no_content
So in PostsController#create action we need to redirect to any action, mostly we redirect to show action. So you need add following line in create action.
# redirects user to show page of newly created post.
if #post.save
redirect_to #post
else
render 'new'
end
Go kill waves :)
I'm building a rails 4.2.0 app with a contact us page (this page does have a semi-empty controller). I'm trying to embed a form partial from another controller.
Here is the code (minus the text):
<% if user_signed_in? %>
<% render 'enquiries/form' %>
<% end %>
When I run this I get the error 'First argument in form cannot contain nil or be empty'.
My enquiries form looks like a basic rails form:
<%= form_for #enquiry do |f| %>
<% if #enquiry.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#enquiry.errors.count, "error") %> prohibited this enquiry from being saved:</h2>
<ul>
<% #enquiry.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :subject, "Subject:" %><br>
<%= f.text_field :subject %>
</div>
<div class="field">
<%= f.label :e_description, "Description:" %><br>
<%= f.text_area :e_description %>
</div>
<div class="actions">
<%= f.submit %>
</div>
What could be the possible reason for the error? Or is there a better way of embedding a view into another?
Update/Edit:
Here's the routes:
devise_for :users
resources :rooms do
resources :viewings
end
resources :rmcats
resources :extras
resources :extracats
resources :enquiries
root :to => redirect('/pages/home')
get 'pages/home'
get 'pages/contactus'
And the enquiry controller:
class EnquiriesController < ApplicationController
before_action :set_enquiry, only: [:show, :edit, :update, :destroy]
# GET /enquiries
def index
#enquiries = Enquiry.all
end
# GET /enquiries/1
def show
end
# GET /enquiries/new
def new
#enquiry = Enquiry.new
end
# GET /enquiries/1/edit
def edit
end
# POST /enquiries
def create
#enquiry = Enquiry.new(enquiry_params)
if #enquiry.save
redirect_to #enquiry, notice: 'Enquiry was successfully created.'
else
render :new
end
end
# PATCH/PUT /enquiries/1
def update
if #enquiry.update(enquiry_params)
redirect_to #enquiry, notice: 'Enquiry was successfully updated.'
else
render :edit
end
end
# DELETE /enquiries/1
def destroy
#enquiry.destroy
redirect_to enquiries_url, notice: 'Enquiry was successfully destroyed.'
end
private
# Use callbacks to share common setup or constraints between actions.
def set_enquiry
#enquiry = Enquiry.find(params[:id])
end
# Only allow a trusted parameter "white list" through.
def enquiry_params
params.require(:enquiry).permit(:subject, :e_description)
end
end
This is the pages controller:
class PagesController < ApplicationController
around_filter :resource_not_found
# def home
# end
private
# If resource not found redirect to root and flash error.
# => For pages this will rarely be needed as it should 404.
def resource_not_found
yield
rescue ActiveRecord::RecordNotFound
redirect_to root_url, :notice => "Page not found."
end
end
Edit:
Log:
Started GET "/pages/contactus" for ::1 at 2015-03-21 01:05:25 +0000
Processing by EnquiriesController#new as HTML
[1m[35mUser Load (0.0ms)[0m SELECT "users".* FROM "users" WHERE "users"."id" = ? ORDER BY "users"."id" ASC LIMIT 1 [["id", 1]]
Rendered enquiries/_form.html.erb (0.0ms)
Rendered pages/contactus.html.erb within layouts/application (0.0ms)
Completed 200 OK in 235ms (Views: 234.6ms | ActiveRecord: 0.0ms)
It is telling you that #enquiry is nil at the time it is trying to render the form. You need to call the new action to create the #enqiury for the form to represent.
You could change your route to:
get 'pages/contactus' => 'enquiries#new'
Then in your Enquiry controller:
def new
#enquiry = Enquiry.new
render 'pages/contactus'
end
EDIT:
Ok, so now we combine what Friends Systems put in his answer:
<% if user_signed_in? %>
<%= render 'enquiries/form' enquiry: #enquiry %>
<% end %>
And now change any instance of #enquiry in the form to enquiry
This is because you need to pass the variable to the partial.
the problem is, that your #enquiry variable is not defined in the context you are rendering the partial.
its not defined by the controller action that gets called, you should create a instance of Enquiry by calling
#enquiry = Enquiry.new
in your action.
In Addition
to use it somewhere else i would pass the #enquiry instance variable as a locale variable to the partial
<% render 'enquiries/form', :enquiry => #enquiry %>
your form method should then look like this:
<%= form_for enquiry do |f| %>
...
<% end %>
of course all the instances vars should be replaced then. just remove the '#'
EDIT:
According to your controller setup you posted above the best way would be to use something like
#enquiry ||= Enquiry.new
in your form partial to make shure a new instance is created if #enquiry is nil.
I'm creating a reddit clone where users can post messages and edit them after posting them. I have the views set up to access the posts and to even make a new post, but when I try to edit a post as an administrator or make a new post as a member, the app flashes an error, saying that the topic is blank.
I'm trying to add user avatars to each post, but I'd like to settle this bug before I move forward. I'm not sure what piece of code is responsible for this, but I've narrowed it down to a few culprits.
It could be the render line here:
<h1>Edit Post</h1>
<div class="row">
<div class="col-md-4">
<p>Guidelines for posts</p>
<ul>
<li>Make sure it rhymes.</li>
<li>Use complete sentences.</li>
<li>Post messages with more than 30 characters.</li>
</ul>
</div>
<div class="col-md-8">
<%= render partial: 'form', locals: { topic: #topic, post: #post } %>
</div>
</div>
Here another file that also has this render partial.
<h1>New Post</h1>
<div class="row">
<div class="col-md-4">
<p>Guidelines for posts</p>
<ul>
<li>Make sure it rhymes.</li>
<li>Use complete sentences.</li>
<li>Post messages with more than 30 characters.</li>
</ul>
</div>
<div class="col-md-8">
<%= render partial: 'form', locals: { topic: #topic, post: #post } %>
</div>
</div>
Lastly is render partial:
<%= form_for [topic, post] do |f| %> <!-- It's kind of like a module! -->
<% if post.errors.any? %>
<div class="alert alert-danger"
<h4>There are <%= pluralize(post.errors.count, "error") %>.</h4>
<ul>
<% post.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<%= form_group_tag(post.errors[:title]) do %>
<%= f.label :title %>
<%= f.text_field :title, class: 'form_control', placeholder: "Enter post title" %>
<% end %>
<%= form_group_tag(post.errors[:body]) do %>
<%= f.label :body %>
<%= f.text_area :body, rows: 8, class: 'form-control', placeholder: "Enter post body" %>
<% end %>
<div class="form-group">
<%= f.submit "Save", class: 'btn btn-success' %>
</div>
<% end %>
What do you think? I'm new to Ruby, and partials are cool, but it's still a new concept. And if this the source of the error, How can I fix it?
EDIT: It was noted that I could be my routes, so here is my routes file.
Rails.application.routes.draw do
devise_for :users
resources :users, only: [:update]
resources :topics do
resources :posts, except: [:index]
end
get 'about' => 'welcome#about'
root to: 'welcome#index'
end
Here's the post_controller also:
class PostsController < ApplicationController # using private methods to Refactor code!
def show
#topic = Topic.find(params[:topic_id])
#post = Post.find(params[:id])
end
def new
#topic = Topic.find(params[:topic_id])
#post = Post.new
authorize #post # from include Pundit in the application controller, authorize is an inherited method
end
def create
#topic = Topic.find(params[:topic_id])
#post = current_user.posts.build(post_params)
authorize #post
if #post.save
flash[:notice] = "Post was saved."
redirect_to [#topic, #post]
else
flash[:error] = "There was an error saving the post. Please try again."
render :new
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])
authorize #post
if #post.update_attributes(post_params)
flash[:notice] = "Post was updated."
redirect_to [#topic, #post]
else
flash[:error] = "There was an error saving the post. Please try again."
render :edit
end
end
private
def post_params
params.require(:post).permit(:title, :body)
end
end
EDIT:
It was noted that the topic_id could be seen as nil, so I looked at the activity log displayed on my terminal.
Started POST "/topics/1/posts" for 127.0.0.1 at 2014-12-12 14:14:46 +0300
Processing by PostsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"glyWpWi1oJpZFuP2g0FvYowq1NG8edZEYzzirnX9pRE=", "post"=>{"title"=>"Hello sdfsd", "body"=>"fdsfsfsd dfdfsdfsfs dsfsdfsfdsfs"}, "commit"=>"Save", "topic_id"=>"1"}
Topic Load (0.1ms) SELECT "topics".* FROM "topics" WHERE "topics"."id" = ? LIMIT 1 [["id", 1]]
User Load (0.1ms) SELECT "users".* FROM "users" WHERE "users"."id" = 8 ORDER BY "users"."id" ASC LIMIT 1
(0.0ms) begin transaction
(0.0ms) rollback transaction
Rendered posts/_form.html.erb (1.4ms)
Rendered posts/new.html.erb within layouts/application (1.8ms)
Completed 200 OK in 73ms (Views: 69.5ms | ActiveRecord: 0.2ms)
Does this mean that the my app recognized the post's topic ID as 1?
Add #post.topic = #topic to your controller after #post is build (to create and update):
...
#post = current_user.posts.build(post_params)
#post.topic = #topic
...
To me this is a strange one.
I have 2 models (with User), I have post and I have comment.
What I am trying to do is to have the form_for comments in the post#show view.
However for some reason when I try to create a comment I get Couldn't find Post without an ID.
When I look at the request parameters though I see:
{"utf8"=>"✓", "authenticity_token"=>"7bAXF66sghTKAF7b61gu08hElC+O1nR6RoT92tqQGOI=", "comment"=>{"content"=>"ok"}, "commit"=>"Add comment", "action"=>"create", "controller"=>"comments", "post_id"=>"23"}
which clearly shows that it does in-fact get the post_id and that it is in this case the id of 23.
After countless hours I thought that I'd see if you guys have a solution.
My comments_controller.rb:
class CommentsController < ApplicationController
before_action :load_post
def create
#comment = #post.comments.build(params[:content])
#comment.user = current_user
if #comment.save
#comment.create_activity :create, owner: current_user
redirect_to root_url, notice: "Comment was created."
else
render :new
end
def load_post
#post = Post.find(params[:id])
end
end
My posts_controller.rb
def show
#post = Post.find(params[:id])
#comment = Comment.new
end
the partial for the forms comments/_form.rb
<%= form_for [#post, #comment] do |f| %>
<%= f.text_area :content %>
<%= f.submit "Add comment" %>
<% end %>
My routes.rb
resources :posts do
resources :comments
end
my posts/show.html.erb
<%= render #post %>
<h3>New comment</h3>
<%= render 'comments/form' %>
my posts/_post.html.erb
<h2><%= #post.title %></h2>
<p><%= #post.content %></p>
<em>written by <%= #post.user.fullname %></em>
You are receiving "post_id" not as "id"
You can make load_post action as private for security concerns
private
def load_post
#post = Post.find(params[:post_id])
end
Access the content like
def create
#comment = #post.comments.build(params[:comment][:content])
....