I am creating my first app, simple blog, and I don't know how to show error messages for nested resource(comments) that doesn't pass validation.
this is create action for comments:
def create
#post = Post.find(params[:post_id])
#comment = #post.comments.create(comment_params)
redirect_to post_path(#post)
end
this is comment form:
<%= form_for([#post, #post.comments.build]) do |f| %>
<p>
<%= f.label :commenter %><br />
<%= f.text_field :commenter %>
</p>
<p>
<%= f.label :text %><br />
<%= f.text_area :text %>
</p>
<p>
<%= f.submit %>
</p>
<% end %>
I tried with:
def create
#post = Post.find(params[:post_id])
#comment = #post.comments.build(comment_params)
if #comment.save
redirect_to post_path(#post)
else
render '/comments/_form'
end
end
and:
<% if #comment.errors.any? %>
<div id="error_explanation">
<h2>
<%= pluralize(#comment.errors.count, "error") %> prohibited
this comment from being saved:
</h2>
<ul>
<% #comment.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
But I don't know whats wrong.
You can't render a partial from a controller. A better alternative is just to create a new view.
class CommentsController
def create
if #comment.save
redirect_to post_path(#post), success: 'comment created'
else
render :new
end
end
end
app/views/comments/new.html.erb:
<% if #comment.errors.any? %>
<div id="error_explanation">
<h2>
<%= pluralize(#comment.errors.count, "error") %> prohibited
this comment from being saved:
</h2>
<ul>
<% #comment.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<%= render partial: 'form', comment: #comment %>
app/views/comments/_form.html.erb:
<%= form_for([#post, local_assigns[:comment] || #post.comments.build]) do |f| %>
<p>
<%= f.label :commenter %><br />
<%= f.text_field :commenter %>
</p>
<p>
<%= f.label :text %><br />
<%= f.text_area :text %>
</p>
<p>
<%= f.submit %>
</p>
<% end %>
Related
The Seller Profile has one seller. I am trying to post the seller profile details and assigning the seller_id to the current_seller. I am however, running into this error. I don't understand why the error says missing parameter because it seems all the needed params have being provided.
Error is get is ActionController::ParameterMissing (param is missing or the value is empty: seller_profiles
def create
#seller_profile = SellerProfile.new(seller_profile_params)
#seller_profile.seller = current_seller
respond_to do |format|
if #seller_profile.save
format.html { redirect_to root_path, notice: 'Seller profile was successfully created.' }
def seller_profile_params
params.require(:seller_profile).permit(:first_name, :other_name, :last_name, :email)
end
<%= form_tag seller_seller_profiles_path do |form| %>
<% if seller_profile.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(seller_profile.errors.count, "error") %> prohibited this seller_profile from being saved:</h2>
<ul>
<% seller_profile.errors.each do |error| %>
<li><%= error.full_message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= label_tag :first_name %>
<%= text_field_tag :first_name %>
</div>
<div class="field">
<%= label_tag :other_name %>
<%= text_field_tag :other_name %>
</div>
<div class="field">
<%= label_tag :last_name %>
<%= text_field_tag :last_name %>
</div>
<div class="field">
<%= label_tag :email %>
<%= text_field_tag :email %>
</div>
<div class="actions">
<%= submit_tag %>
</div>
<% end %>
resources :sellers, only: [:new, :create, :show, :index, :destroy] do
resources :seller_profiles
end
You should use the form_for or the form_with helpers instead of form_tag. Those helper methods will take care of adding the wrapping seller_profile key.
<%= form_for seller_profile do |form| %>
<% if seller_profile.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(seller_profile.errors.count, "error") %> prohibited this seller_profile from being saved:</h2>
<ul>
<% seller_profile.errors.each do |error| %>
<li><%= error.full_message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= form.label :first_name %>
<%= form.text_field :first_name %>
</div>
<div class="field">
<%= form.label :other_name %>
<%= form.text_field :other_name %>
</div>
... replicate the same change for the rest of the fields ...
<div class="actions">
<%= form.submit %>
</div>
<% end %>
If the error is (param is missing or the value is empty: seller_profiles, it's because you require :seller_profile, not :seller_profiles in your params.require
So im learning rails, and following the rails getting started guide (I've actually done the "blog app" on the Udemy rails course, but im making sure I can write it from scratch first before moving on).
Anyways, i've gotten Delete/Create running, but I was adding validation...and while the validation works my errors aren't showing up.
Right now my pages are super simple:
new.html.erb
<% if #user.errors.any? %>
<div id="error_explanation">
<h2>
<%= pluralize(#user.errors.count, "error") %> prohibited this user from being saved
</h2>
<ul>
<% #user.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<%= form_with scope: :user, url: users_path, local: true do |form| %>
<p>
<%= form.label :username %><br>
<%= form.text_field :username %>
</p>
<p>
<%= form.label :name %><br>
<%= form.text_field :name %>
</p>
<p>
<%= form.label :age %><br>
<%= form.number_field :age %>
</p>
<p><%= form.submit %></p>
<% end %>
users_controller
class UsersController < ApplicationController
def index
#users = User.all
end
def new
#user = User.new
end
def edit
#user = User.find(params[:id])
end
def create
#user = User.new(params.require(:user).permit(:username,:name,:age))
if #user.save
redirect_to users_path
else
render 'new'
end
end
def update
end
def destroy
#user = User.find(params[:id])
#user.destroy
redirect_to users_path
end
end
So the weird thing if I go into my network tab in dev tools I can see this show up in the response tab:
<div id="error_explanation">
<h2>
1 error prohibited this user from being saved
</h2>
<ul>
<li>Username has already been taken</li>
</ul>
</div>
But it doesn't show up in "elements" in Chrome dev tools. I've restarted rails....so Im really not sure why the elements are not showing up. I DO have bootstrap 4.00 beta installed, but not sure why that would matter. This is rails 5.1.4 btw.
This is because you are not getting the same #user in the <% if #user.errors.any? %>
Try this :
<%= form_with scope: :user, url: users_path, local: true do |form| %>
<% if #user.errors.any? %>
<div id="error_explanation">
<h2>
<%= pluralize(#user.errors.count, "error") %> prohibited this user from being saved
</h2>
<ul>
<% #user.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<p>
<%= form.label :username %><br>
<%= form.text_field :username %>
</p>
<p>
<%= form.label :name %><br>
<%= form.text_field :name %>
</p>
<p>
<%= form.label :age %><br>
<%= form.number_field :age %>
</p>
<p><%= form.submit %></p>
<% end %>
I am trying to create a form for a site administrator to associate events with a list of previous speakers. The administrator navigates to the speaker, clicks on a button to "Add to event" and a form comes up asking for which event the speaker is attending. The speaker is supposed to be passed in as a hidden field, and the events are listed via a collection select. Unfortunately, the speaker id is not passing into the database when I submit the form.
Why is my form is not saving values from the hidden field, and how do I about fixing this? Values from the collection select are passing.
<%= form_for(#event_speaker) do |f| %>
<% if #event_speaker.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#event_speaker.errors.count, "error") %> prohibited this event_speaker from being saved:</h2>
<ul>
<% #event_speaker.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<p><%= #speaker.first_name %></p>
<div class="actions">
<%= #speaker.id %>
<%= f.hidden_field(:speaker) %>
<%= hidden_field_tag('speaker_id',#speaker.id) %>
</div>
<div class="field">
<%= f.label :event %><br>
<%= f.collection_select(:event_id, #upcoming_events, :id, :name)%>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
And the controller:
def new
#event_speaker = EventSpeaker.new
#speaker = Speaker.find(params[:speaker_id])
#event_speaker.speaker_id = #speaker
#Time = Time.now
#upcoming_events = Event.all
end
# GET /event_speakers/1/edit
def edit
end
# POST /event_speakers
# POST /event_speakers.json
def create
#event_speaker = EventSpeaker.new(event_speaker_params)
respond_to do |format|
if #event_speaker.save
format.html { redirect_to #event_speaker, notice: 'Event speaker was successfully created.' }
format.json { render action: 'show', status: :created, location: #event_speaker }
else
format.html { render action: 'new' }
format.json { render json: #event_speaker.errors, status: :unprocessable_entity }
end
end
end
And...
def event_speaker_params
params.require(:event_speaker).permit(:speaker_id,:event_id)
end
You should do
<%= f.hidden_field :speaker_id, :value => #speaker.id %>
This will generate your speaker_id nested inside event_speaker so your form will look like this:
<%= form_for(#event_speaker) do |f| %>
<% if #event_speaker.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#event_speaker.errors.count, "error") %> prohibited this event_speaker from being saved:</h2>
<ul>
<% #event_speaker.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<p><%= #speaker.first_name %></p>
<div class="actions">
<%= f.hidden_field :speaker_id, :value => #speaker.id %>
</div>
<div class="field">
<%= f.label :event %><br>
<%= f.collection_select(:event_id, #upcoming_events, :id, :name)%>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
For details checkout hidden field in rails
I have the following:
routes.rb:
resources :posts do
resources :replies
end
replies_controller.rb:
class RepliesController < ApplicationController
def create
#post = Post.find(params[:post_id])
#reply = #post.replies.build(params[:reply])
#reply.user_id = current_user.id
if #reply.save
flash[:success] = "reply created!"
redirect_to post_path(#post)
else
redirect_to post_path(#post)
end
end
replies/_form.html.erb:
<%= form_for([#post, #post.replies.build]) do |f| %>
<%= render 'shared/error_messages', object: f.object, target: #reply %>
<div class="field">
<%= f.text_area :content, placeholder: "Enter reply content" %>
</div>
<%= f.submit "Reply", class: "btn btn-large btn-primary" %>
<% end %>
posts/show.html.erb:
<div class="span8">
<%= render 'replies/form' %>
</div>
shared/error_messages.html.erb:
<% if object.errors.any? %>
<div id="error_explanation">
<div class="alert alert-error">
The form contains <%= pluralize(object.errors.count, "error") %>.
</div>
<ul>
<% object.errors.full_messages.each do |msg| %>
<li>* <%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
I'm not sure why the errors messages for the replies are not displaying since I'm using target: #reply (:content and :user_id are required).
Any suggestions to fix this?
In create method's else section you have to render the post_path(#post) not redirect the post_path(#post)
try this in else part of create section
render :template => 'posts/show'
So that your current #reply object will persist for your error messages.
redirect_to post_path(#post) will redefine #reply object in show action (I assume you have defined #reply object there).
In posts/show action, build your reply object there and assign it to #reply instance object.
#reply = #post.replies.build
Now in replies/_form.html.erb:
change #post.replies.build to #reply
i.e
<%= form_for([#post, #post.replies.build]) do |f| %>
to
<%= form_for([#post, #reply]) do |f| %>
Also assign #reply to object variable while rendering 'shared/error_messages' partial,
<%= form_for([#post, #reply]) do |f| %>
<%= render :partial => 'shared/error_messages', :locals => {:object => #reply} %>
<div class="field">
<%= f.text_area :content, placeholder: "Enter reply content" %>
</div>
<%= f.submit "Reply", class: "btn btn-large btn-primary" %>
<% end %>
Also make partial for error_messages in shared folder (shared/_error_messages). In this partial paste your code which is in shared/error_messages
<% if object.errors.any? %>
<div id="error_explanation">
<div class="alert alert-error">
The form contains <%= pluralize(object.errors.count, "error") %>.
</div>
<ul>
<% object.errors.full_messages.each do |msg| %>
<li>* <%= msg %></li>
<% end %>
</ul>
</div>
Running Rails 3.2.1.
I went through the "Getting started" guide on the Ruby on Rails site. I have set up a blog post where someone can comment on the posts.
I modified the example to show an error when I enter in comments that don't validate (no name or comment text).
(A post has multiple comments, etc.)
However, how do I have Rails put this problematic comment back in the form, instead of the page?
Here is my create method in the comments controller:
def create
#post = Post.find(params[:post_id])
#comment = #post.comments.build(params[:comment])
respond_to do |format|
if #comment.save
format.html { redirect_to(#post, :notice => 'Comment was successfully created.') }
else
format.html { render 'posts/show' }
end
end
end
Here is my show.html.erb from posts:
<%= render #post %>
<h3>Comments</h3>
<%= render #post.comments %>
<h3>Add a comment</h3>
<%= render "comments/form" %>
<p>
<% if user_signed_in? %>
<%= link_to 'Edit', edit_post_path(#post) %> |
<% end %>
<%= link_to 'Back', posts_path %>
</p>
And here is my comment form partial:
<%= form_for([#post, #post.comments.build]) do |f| %>
<%= render "shared/error_messages", :target => #comment %>
<div class="field">
<%= f.label "Name" %><br />
<%= f.text_field :name %>
</div>
<div class="field">
<%= f.label :body %><br />
<%= f.text_area :body %>
</div>
<div class="actions">
<%= f.submit "Add Comment!" %>
</div>
<% end %>
And here's my comment partial:
<p>
<strong><%= comment.name %></strong><br />
<%= comment.created_at.try(:strftime, "on %A, %B %d %Y at %H:%M:%S") %><br />
<%= simple_format(h(comment.body), :sanitize => true) %>
</p>
In your form when you return from an error.
<% if #comment.errors.any? %>
<div id="errorExplanation">
<h2><%= pluralize(#comment.errors.count, "error") %> prohibited this post from being saved:</h2>
<ul>
<% #comment.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>