Can't render validations errors in form partial - ruby-on-rails

I try to render validation errors in a form partial.
I have :
resas/_form.html.erb
<%= form_for ([#resa, Resa.new]) do |f| %>
<% if #resa.errors.any? %>
<% #resa.errors.full_messages.each do |msg| %>
<h3><%= msg %></h3>
<% end %>
<% end %>
...
<div class="actions">
<%= f.submit %>
</div>
I dislay this form in the index view, through another partial called _agenda :
resas/index.html.erb
<%= render "shared/agenda" %>
shared/_agenda.html.erb
<%= render "resas/form" %>
In the controller :
def create
#resa = Resa.new(params[:resa])
respond_to do |format|
if #resa.save
format.html { redirect_to resas_path, notice: 'Resa was successfully created.' }
format.json { render json: #resa, status: :created, location: #resa }
else
format.html { redirect_to resas_path }
format.json { render json: #resa.errors, status: :unprocessable_entity }
end
end
end
I would like to redirect to the index action, and render validation errors, but I can't.
I have :
NoMethodError in Resas#index
undefined method `errors' for nil:NilClass
how could I do ?
Thanks for your help

you can render to index action instead redirect in else part

Related

Call create action from different controller

I would like to create a booking from bookings#new and rooms#show. When I try to create it from bookings#new it works, but when try to create it from rooms#show it shows me the error:
1 error prohibited this booking from being saved, room must exist.
Here is the code I'm using:
BookingsController:
def create
if #room
#room = Room.find(params[:room_id])
#booking = #room.bookings.create(booking_params)
if #booking.save
redirect_to room_path(#room)
else
render :new
end
else
#booking = Booking.new(booking_params)
respond_to do |format|
if #booking.save
format.html { redirect_to #booking, notice: 'Booking was successfully created.' }
format.json { render :show, status: :created, location: #booking }
else
format.html { render :new }
format.json { render json: #booking.errors, status: :unprocessable_entity }
end
end
end
end
views/rooms/show.html.erb
<h2>book this room:</h2>
<%= form_with(model: [ #room, #room.bookings.build ], local: true) do |form| %>
<p>
<%= form.label :traveller %>
<%= form.text_field :traveller %>
</p>
<p>
<%= form.label :startfrom %>
<%= form.datetime_select :startfrom %>
</p>
<p>
<%= form.label :endsat %>
<%= form.datetime_select :endsat %>
</p>
<p>
<%= form.label :bookingref %>
<%= form.text_field :bookingref %>
</p>
<p>
<%= form.submit %>
</p>
<% end %>
Your mistake is inside if-else in the controller. You're checking #room before you define it, so it is always nil. It should be:
def create
# use find_by here, otherwise you get RecordNotFound error
#room = Room.find_by(id: params[:room_id])
if #room
# use build, because create saves the instance
#booking = #room.bookings.build(booking_params)
if #booking.save
redirect_to room_path(#room)
else
# I suppose you don't want render bookings/new view here
render 'books/show'
end
else
#booking = Booking.new(booking_params)
respond_to do |format|
# redirect and render logic goes here. BTW, do you really need json response format?
end
end
end
end
Also, define in rooms#show action
#booking = #room.bookings.build
and use the instance in the form to correctly display validation errors
form_with(model: [#room, #booking], local: true) do |form|

Rails artifact when changing the arrangement of elements in the form of

When you change the items in the form of an artifact appears , help me to understand what is the reason ?
view project#show:
<div class="container">
<h3><%= #project.name %></h3>
<h2>Tasks</h2>
<table class="table table-striped" id="tasks_list">
<%= render #project.tasks %>
</table>
<h2>Add a task:</h2>
<%= render 'tasks/form' %>
<%= link_to 'Back', projects_path %>
</div>
screenshot#1
If you change tasks list and add from:
<div class="container">
<h3><%= #project.name %></h3>
<h2>Add a task:</h2>
<%= render 'tasks/form' %>
<h2>Tasks</h2>
<table class="table table-striped" id="tasks_list">
<%= render #project.tasks %>
</table>
<%= link_to 'Back', projects_path %>
</div>
screenshot#2
Task list size has not changed - but there was a strange artifact.
Update
view task#_form.html.erb:
<%= form_for([#project, #project.tasks.build], remote: true) do |f| %>
<div class="input-group">
<div aria-describedby="add_project">
<%= f.text_field :name, class: 'form-control ' %>
</div>
<span class="input-group-btn">
<%= f.submit 'Добавить', class: 'btn btn-success btn-secondary', id: "add_project" %>
</span>
</div>
<% end %>
Task Controller:
def create
#project = Project.find(params[:project_id])
#task = #project.tasks.create(task_params)
respond_to do |format|
if #task.save
format.html { redirect_to #project, notice: 'Task was successfully created.' }
format.js {}
format.json { render json: #task, status: :created, location: #task }
else
format.html { render action: "new" }
format.json { render json: #task.errors, status: :unprocessable_entity }
end
end
end
def destroy
#task = Task.find(params[:id])
#task.destroy
respond_to do |format|
format.html { redirect_to products_path, success: 'Task destroyed successfully' }
format.js {}
end
end
private
def task_params
params.require(:task).permit(:name)
end
Project Controller:
def index
#projects = Project.all
#project = Project.new
end
def show
#project = Project.find(params[:id])
end
def edit
#article = Project.find(params[:id])
end
def create
#project = Project.new(project_params)
respond_to do |format|
if #project.save
format.html { redirect_to #project, notice: 'Project was successfully created.' }
format.js {}
format.json { render json: #project, status: :created, location: #project }
else
format.html { render action: 'new' }
format.json { render json: #project.errors, status: :unprocessable_entity }
end
end
end
Added to the form: <%= form_for([#project, #project.tasks.klass.build], remote: true) do |f| %>
Now error:
NoMethodError in Projects#show
Showing /Users/alexandr.dmitrenko/todolist/app/views/tasks/_form.html.erb where line #1 raised:
undefined method `build' for #<Class:0x007ffde19efea8>
Extracted source (around line #1):
1<%= form_for([#project, #project.tasks.klass.build], remote: true) do |f| %>
The reason is this bit:
#project.tasks.build
in your form. What it does it builds a new, non-saved Task record and stores it within association. Every further call to #project.tasks will return the usual results (from database) + this new record. What you need to do is to replace it with:
#project.tasks.scope.build
scope method will return new instance of the association, so it is safe to call build on it as it will not be stored anywhere and won't affect your original association object.

How to make ajax call and show error messages

Two of the action of My registration controller is new and create.
def new
#regist = Regist.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: #regist }
end
end
def create
#regist = Regist.new(regist_params)
respond_to do |format|
if #regist.save
format.html { redirect_to #regist, notice: 'Regist was successfully created.' }
format.json { render json: #regist, status: :created, location: #regist }
else
format.html { render action: "new" }
format.json { render json: #regist.errors, status: :unprocessable_entity }
end
end
end
And the new form contain following code.
<%= form_for(#regist) do |f| %>
<% if #regist.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#regist.errors.count, "error") %> prohibited this regist from being saved:</h2>
<ul>
<% #regist.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.collection_select :student_id, Student.all, :id, :name %><br />
</div>
<div class="field">
<%= f.collection_select :semester_id, Semester.all, :id, :name %><br />
</div>
<div class="field">
<% for subject in Subject.find(:all) %>
<%= check_box_tag "regist[subject_ids][]", subject.id %>
<%= subject.name %><br>
<% end %>
</div>
<div class="field">
<%= f.label :date_of_birth %><br />
<%= f.text_field :date_of_birth %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
Now, when someone click on submit button I want to make ajax call using remote true if there are validation errors and show the errors without reloading the page. And if there are no validation errors I want the user to be redirected to show page. How can I do this?
First of all you should add a remote: true to your existing form to allow remote action.
TODO this just add on the first line of your form the remote: true,
<%= form_for(#regist, remote: true) do |f| %>
the rest leave it as it is. Then you need to make your controller to respond to remote calls, therefore you need to alter the responds_to block of create action:
respond_to do |format|
if #regist.save
format.html { redirect_to #regist, notice: 'Regist was successfully created.' }
format.json { render json: #regist, status: :created, location: #regist }
format.js { render js: "window.location.href='"+regists_path+"'"}
else
format.html { render action: "new" }
format.json { render json: #regist.errors, status: :unprocessable_entity }
format.js
end
end
The last step you have to do is to add a file to your app/views/regists/ directory
where you should add a create.js.erb file:
<% if #regist.errors.any? %>
$('#new_regist').effect('highlight', { color: '#FF0000'}, 1000); // for highlighting
// or add here whatever jquery response you want to have to your views.
<% end %>
You will get your validation errors displayed like before above the form.
You have to add the redirect to your controller to the desirable action of your choice. I have added for you a window.location.href as a response to the regists_path.

ActiveRecord::RecordNotFound

I am trying to submit a form and getting this error: Couldn't find Event without an ID
Here is the controller:
def create
#event = Event.find(params[:event_id])
#event_sponsorship = EventSponsorship.new(params[:event_sponsorship])
#event_sponsorship.sponsor_id = current_user.id
#event_sponsorship.event_id = #event
respond_to do |format|
if #event_sponsorship.save
format.html { redirect_to #event_sponsorship, notice: 'Event sponsorship was successfully created.' }
format.json { render json: #event_sponsorship, status: :created, location: #event_sponsorship }
else
format.html { render action: "new" }
format.json { render json: #event_sponsorship.errors, status: :unprocessable_entity }
end
end
end
Here is the form:
<%= simple_form_for(#event_sponsorship) do |f| %>
<%= f.error_notification %>
<div class="signin">
<%= f.hidden_field :event_id, value: #event %>
<%= f.hidden_field :sponsor_id, value: current_user.id %>
<%= f.button :submit, :class => "btn btn-success btn-block", value: "Yes" %>
</div>
<% end %>
In the create method the event_id should be found from the URL. Where am I going wrong?
Post your error as seen in your server console, you'll see that your param 'event_id' is a sub key of (I guess) 'event_sponsorship'
Try this:
#event = Event.find(params[:event_sponsorship][:event_id])
And it's even possible that you'll need to use this code:
#event = Event.find(params[:event_sponsorship].delete(:event_id))
That would remove the 'event_id' fron your params, and allow EventSponsorship.new to work without error

Rails 3.2 - Nested Resource Passing ID

Okay so my associations are:
Outlet -> has_many :monitorings
Monitoring -> belongs_to :outlet
My Routes:
resources :outlets do
resources :monitorings
end
View:
<%= link_to new_outlet_monitoring_path(#outlet) %>
When I click the link, the logs show that the outlet_id is passed as a parameter to the new page correctly.
But when saving the monitoring record, the outlet_id becomes nil.
Any help?
UPDATE:
# views/monitorings/_form.html.erb
<%= form_for(#monitoring) do |f| %>
<h2>Type of Monitoring</h2>
<fieldset data-role="controlgroup" >
<div class="radio-group">
<%= f.radio_button :mtype, "Full" %><%= f.label :mtype, "Full", value: "Full" %>
<%= f.radio_button :mtype, "Partial" %><%= f.label :mtype, "Partial", value: "Partial" %>
<%= f.radio_button :mtype, "None" %><%= f.label :mtype, "None", value: "None" %>
</div>
</fieldset>
<hr>
<%= f.submit "Next Step" %>
<% end %>
And the controller:
# controllers/monitoring_controller.rb
def new
#monitoring = Monitoring.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: #monitoring }
end
end
def create
#monitoring = Monitoring.new(params[:monitoring])
respond_to do |format|
if #monitoring.save
format.html { redirect_to #monitoring, notice: 'Monitoring was successfully created.' }
format.json { render json: #monitoring, status: :created, location: #monitoring }
else
format.html { render action: "new" }
format.json { render json: #monitoring.errors, status: :unprocessable_entity }
end
end
end
This is most likely an issue with the way you are creating the new monitoring record. Can we see your form and your create controller action?

Resources