Rails Remote True Ajax ActionController::UnknownFormat - ruby-on-rails

I have a mini-update method in my model that only updates one field, set up in a chart (so I see the form for each row). It works properly, but want it to update using AJAX to be able to do multiple updates quickly without waiting for a full page reload.
The cell looks like this:
<td style="min-width: 150px" id="goody_cell<%= blog.id %>">
<%= render partial: "admin/goody_cell", locals: { blog: blog } %>
</td>
With this as the partial:
<% if blog.variation_id %>
<%= Variation.find(blog.variation_id).name %>
<% end %>
<%= simple_form_for(blog, url: update_goody_path(blog), remote: true, method: :patch, authenticity_token: true) do |f| %>
<% variation_collection = [] %>
<% Variation.all.each do |lm| %>
<% variation_collection << ["#{lm.name}", "#{lm.id}"] %>
<% end %>
<div class="row text-left">
<div class="form-group col-12 mb-0 pb-0">
<%= f.input :variation_id, label: false, prompt: "Choose a Related Goody", input_html: { id: "lmFor" + blog.id.to_s, class: 'browser-default', onchange: "this.form.submit();" }, collection: variation_collection, required: false %>
</div>
</div> <!-- row -->
<% end %>
My blogs/update_goody.js.erb looks like this:
$('#goody_cell<%= blog.id %>').html('<%= j render partial: "admin/goody_cell", locals: { blog: #blog } %>');
And my controller method is like this:
def update_goody
#blog = Blog.friendly.find(params[:id])
if #blog.update!(blog_params)
respond_to do |format|
format.js
end
else
format.html { render :edit }
format.json { render json: #blog.errors, status: :unprocessable_entity }
end
end
I have the route like this:
patch "blogs/:id/update_goody" => "blogs#update_goody", as: "update_goody"
When I try to update it, it does update the value, but before it renders the partial, I get an error saying:
ActionController::UnknownFormat - ActionController::UnknownFormat:
app/controllers/blogs_controller.rb:178:in `update_goody'
I've looked at SO posts like this but they all say that the error was fixed by adding remote: true, which I already have.
Can anyone help me get this working?

instead of remote: true, use local: false (Rails 6)

make sure you have both update_goody.html.erb and update_goody.js.erb in your views/blogs folder.
you dont have to add anything to update_goody.html.erb as its not rendering at all.
in your controller
def update_goody
#blog = Blog.friendly.find(params[:id])
if #blog.update!(blog_params)
respond_to do |format|
format.html
format.js
end
else
format.html { render :edit }
format.json { render json: #blog.errors, status: :unprocessable_entity }
end
end
note that format.html in respond_to block. it dosent matter you add it or not as you are set remote: true in your form
refer this

In my case i had to put redirect_to to render html
respond_to do |format|
format.js
format.html { redirect_to update_goody_path }
end

Related

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.

Ruby on rails, radio button if

I'm a little green with ruby but wanted to try something with it, so I want to ask you for help. I have a problem with radio buttons. I have succesfully created a radio buttons, like this:
<input id="user_options_true" name="user[options]" type="radio" value="true" />
<label class="collection_radio_buttons" for="user_options_true">Tak</label>
<input id="user_options_false" name="user[options]" type="radio" value="false" />
<label class="collection_radio_buttons" for="user_options_false">Nie</label>
But now I would like to do if statement on the other page that woudl work like this: if value true, Write text, if false, write different text. I tried doing it like this :
<% if user[options] == true %>
<b>Status:Ma doktora </b>
<% if user[options] == false %>
<b>Status:Nie ma doktora</b>
But I get error like this:
F:/p15/app/views/pacjencis/show.html.erb:47: syntax error, unexpected keyword_ensure, expecting keyword_end
F:/p15/app/views/pacjencis/show.html.erb:49: syntax error, unexpected $end, expecting keyword_end
My view:
<%= simple_form_for(#pacjenci, html: {class: "form-horizontal"}) do |f| %>
<%= f.error_notification %>
<div class="form-inputs">
<%= f.input :name %>
<%= f.input :last_name %>
<%= f.input :adres %>
<%= f.input :pesel %>
<%= f.input :telefon %>
<%= f.input :email %>
Czy lekarz przyjmował
<input id="user_options_true" name="user[options]" type="radio" value="true" />
<label class="collection_radio_buttons" for="user_options_true">Tak</label>
<input id="user_options_false" name="user[options]" type="radio" value="false" />
<label class="collection_radio_buttons" for="user_options_false">Nie</label>
</div>
<div class="form-actions">
<%= f.button :submit %>
</div>
<% end %>
My controler:
> class PacjencisController < ApplicationController
# GET /pacjencis
# GET /pacjencis.json
def index
#pacjencis = Pacjenci.all
respond_to do |format|
format.html # index.html.erb
format.json { render json: #pacjencis }
end
end
# GET /pacjencis/1
# GET /pacjencis/1.json
def show
#pacjenci = Pacjenci.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render json: #pacjenci }
end
end
# GET /pacjencis/new
# GET /pacjencis/new.json
def new
#pacjenci = Pacjenci.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: #pacjenci }
end
end
# GET /pacjencis/1/edit
def edit
#pacjenci = Pacjenci.find(params[:id])
end
# POST /pacjencis
# POST /pacjencis.json
def create
#pacjenci = Pacjenci.new(params[:pacjenci])
respond_to do |format|
if #pacjenci.save
format.html { redirect_to #pacjenci, notice: 'Pacjenci was successfully created.' }
format.json { render json: #pacjenci, status: :created, location: #pacjenci }
else
format.html { render action: "new" }
format.json { render json: #pacjenci.errors, status: :unprocessable_entity }
end
end
end
# PUT /pacjencis/1
# PUT /pacjencis/1.json
def update
#pacjenci = Pacjenci.find(params[:id])
respond_to do |format|
if #pacjenci.update_attributes(params[:pacjenci])
format.html { redirect_to #pacjenci, notice: 'Pacjenci was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: #pacjenci.errors, status: :unprocessable_entity }
end
end
end
# DELETE /pacjencis/1
# DELETE /pacjencis/1.json
def destroy
#pacjenci = Pacjenci.find(params[:id])
#pacjenci.destroy
respond_to do |format|
format.html { redirect_to pacjencis_url }
format.json { head :no_content }
end
end
end
Would really apreciate help.Thanks in advance.
<% if params[:user][:options] == 'true' %>
<b>Status:Ma doktora </b>
<% else %>
<b>Status:Nie ma doktora</b>
<% end %>
I'd recommend using <strong> tags instead of <b>.
For true or false values you'd usually use <% if params[:user][:options]? %> but since this is an actual string value and not a boolean, the answer above should work.
The params part is how you access POST and GET data passed from your forms.
You need to add elsif and end like below:
<% if user[options] == true %>
<b>Status:Ma doktora </b>
<% elsif user[options] == false %>
<b>Status:Nie ma doktora</b>
<% end %>
<b><%= params[:user][:options]? ? 'Status:Ma doktora' : 'Status:Nie ma doktora' %></b>
This solution uses a ternary operator: See How do I use the conditional operator (? :) in Ruby?

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.

Can't render validations errors in form partial

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

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