Why is Ajax request not working as intended in rails [duplicate] - ruby-on-rails

I need to render an html code I receive from an API.
In Rails 6 : I was doing this in my controller, and it was working fine. I called the webservice I received the response, and I was redirected to the code generated by the render. Fine !
class GatewayController < ApplicationController
def new
init_gateway_call
end
def create
call_gateway
render_gateway_response
end
private
...
def render_gateway_response
render(html: #gateway_response.message.html_safe)
end
end
new.html.erb :
<%= form_with url: gateway_path, local: true do |f| %>
...
<% end %>
And no : create.html.erb
** Rails 7 **
I call the webservice. I get the answer but my page idle and I get this error.
Error: Form responses must redirect to another location at FormSubmission.requestSucceededWithResponse (application-0f0c10fb8f5683e32fc53a93a8a323c328de61682ca16fb65a6a2b8a3ba5d087.js:1614)
at FetchRequest.receive (application-0f0c10fb8f5683e32fc53a93a8a323c328de61682ca16fb65a6a2b8a3ba5d087.js:1390)
at FetchRequest.perform (application-0f0c10fb8f5683e32fc53a93a8a323c328de61682ca16fb65a6a2b8a3ba5d087.js:1374)
So far, I tried:
# GatewayController
respond_to :create, format: :html, gateway_response: #gateway_response.message.html_safe
<%= gateway_response %>
Without success ... Do you have any idea? Otherwise it is going to be a long weekend ^^

I figured it out you while posting my question. The error message seems like a Turbo error. I had to had data-turbo false to my form.
<%= form_with url: gateway_path, local: true, data: { turbo: false } do |f| %>
...
<% end %>
And keep my controller like it was.
render(html: #gateway_response.message.html_safe)
Happy upgrade anyone

Setting data: {turbo: false} will cause the page to reload entirely. This takes away the entire point of turbo which is to reduce page reloads.
The reason the error occurs is because Turbo expects a 303 redirect response. The solution is to have the server respond with 422 or 500 status code when you are not redirecting.
if save
redirect_to root_path
else
render :new, status: 422
You can read about this here: https://turbo.hotwired.dev/handbook/drive#redirecting-after-a-form-submission
Of course, if you want the page to reload, you can use data-turbo: false

Thanks! I'm also developing on Rails 7 and data: { turbo: false } fixed my issue.

Instead of using turbo: false as suggested on the answer you need to add appropriate status like :see_other for redirects and 422 (unprocessible_entity) in case render.
render :new, status: 422
redirect_to xyz_path, status: :see_other

Related

ActionController::UnknownFormat in Controller ( #index)

I have a link_to calling my #index. In this method lies a respond_to for a format.js so I can initiate some Ajax. Things is, when I look at the console I get an error 500 because of a "ActionController::UnknownFormat"
I have tested out differents solutions from older posts, but I can't figure out what I'm missing.
controler :
def index
respond_to do |format|
format.js { render partial: 'private/messages/load_more_messages' }
end
end
view :
<%= link_to "Load messages", private_messages_path(:conversation_id => conversation.id), remote: true %>
Does anyone have any thoughts on this ? It's supposed to be a text book case, but I've been hitting my heads against a brick wall with this one.
If you are loading a HTML partial try it like this:
def index
render partial: 'private/messages/load_more_messages'
end
Although i would recommend making a specific endpoint for fetching partials that you pass a route to since this might be something you do frequently in a project.
Something like this
def render_partial(partial_route)
render partial: partial_route
end
Well, after going around testing a wide range of ideas, I came back to my original thought and it worked perfectly. I don't know what went wrong the first time but now it is perfect.

Deleting a has_many_attached Item in Active Storage Rails 5.2

I'm trying to create a delete method to delete an image that relates to an event in Rails. I've actually gotten it to work before sending on the code but my problem now is making the action happen with Ajax. The below code works and refreshes my form page with the updated images list.
Event.rb
has_many_attached :images
Admin_events_controller
def destroy_single_image
#event_image = ActiveStorage::Attachment.find_by(blob_id)
#event_image.purge
redirect_back(fallback_location: request.referer)
end
View
<% if #event.images.any? %>
<% #event.images.each do |event_image| %>
<%= image_tag event_image, height: "100" %>
<%= link_to 'Remove', destroy_single_image_admin_events_path(id: event_image.id),
method: :delete,
data: { confirm: 'Are you sure?' } %>
<% end %>
<% end %>
routes
resources :events do
collection do
get 'destroy_multiple_images'
# get 'destroy_single_image'
post 'destroy_single_image', action: "destroy_single_image"
end
end
Request Paramaters (Old request parameters which led me to change my action in the routes file. Am I correct in doing this? It works now as above but i'm afraid of any security issues)
{"_method"=>"delete", "authenticity_token"=>"CrL7UAG671aSMiIVL6slvukHWT5S1YEaSEEdgtu1m8PKGm0deZk15uoPhXzhq/1oLNVp5otd8ai55tM0sLNGpw==", "controller"=>"admin/events", "action"=>"destroy", "id"=>"destroy_single_image", "format"=>"769"}
So my issue is now with respond_to :js in the destroy_single_image method. If I add this like below.
Admin_events_controller
def destroy_single_image
#event_image = ActiveStorage::Attachment.find(params[:id])
#event_image.purge
respond_to :js
#redirect_back(fallback_location: request.referer)
end
I know receive an error in my server logs.
This i'm guessing has to do with the routes action call? I've not added the js file but it's in the same folder as the events controller and called the same as the method destory_single_image.js.erb
Anybody able to shed some light on this please? Thank you.
So to recap. The above code works normally but refreshed the edit form page as the server is called. I'm now getting errors when trying to make the call remote: true and have the respond_to :js in my controller. :D

How to fix controller redirect after removing turbolinks in Rails

I've removed turbolinks from my Rails 6.0.0 beta web application using Ruby 2.6.1 and upon doing so, whenever I update or create a chapter, a POST request will get sent to the database. But while the database will save the data, it will also try to redirect the page, but the browser does not redirect to anywhere and will still display the edit/new page.
This was not an issue before removing turbolinks. I have tried searching around but could not find any solution to this so far. I tried restarting the server and of course using bundle update beforehand to actually remove turbolinks.
Chapter Controller
def update
#book = Book.find(params[:book_id])
#chapter = #book.chapters.find(params[:id])
if #chapter.update(chapter_params)
redirect_to book_chapter_path(#book, #chapter)
else
...
end
end
...
private
def chapter_params
params.require(:chapter).permit(:title, :content, :status)
end
chapters > edit.html.erb
<%= form_with model: #chapter, url: { action: "update" } do |form| %>
...
<%= form.submit "Draft", class: "save-btn" %>
...
<% end %>
routes.rb
resources :books do
resources :chapters
end
Normally I expect this output from the server logs after it's POST request to update/create the chapter in the database...
Started GET "/books/1/chapters/1" for 127.0.0.1 at 2019-02-17 12:52:29 +1030
Processing by ChaptersController#show as HTML
But instead, it says
Started GET "/books/1/chapters/1" for 127.0.0.1 at 2019-02-17 12:52:29 +1030
Processing by ChaptersController#show as JS
I think I understand why this is happening, but again, I don't know how to solve it.
Default of form_with is Ajax(remote).
https://api.rubyonrails.org/classes/ActionView/Helpers/FormHelper.html#method-i-form_with
You should add local: true.
<%= form_with model: #chapter, url: { action: "update" }, local: true do |form| %>

link_to white remote => true throws a 406 error on IE

I've a very big problem when updating to rails 3.
If I use this:
= link_to "Show Parent Text", show_parent_path(c.id), :remote => true, :method => :get
It works great at Firefox and the controller responds normaly:
respond_to do |format|
format.js do
render :update do |page|
page.replace_html "original_#{#h.id}", :partial => "texts/original"
end
end
end
But Internet Explorer 9 handles the link with a GET request to show_parent_path(c.id) instead of using the AJAX request, resulting in a 406 error page.
How can I fix this? I'm having this issue with Rails 3.0.5. Thanks a lot in advance!
For me the error occurred having an error in the JavaScript code. Eliminating this worked for me.
Maybe this helps you, too?

Redirecting to a 500 page when an AJAX call fails in Ruby on Rails

I'm working with an application built in Ruby on Rails with very poor error handling right now. If a controller method is executed via ajax, and that method results in a 500 (or 404 or any other response) the 500.html page is rendered and returned as the result to the AJAX request. Obviously the javascript doesn't know what to do with that HTML and the web page looks like it's just waiting for a response.
Is there an easy way in rails to render an error.rjs template anytime an error occurs during an AJAX call?
You can use respond_to inside a controller's rescue_action or rescue_action_in_public method. Consider the following controller:
class DefaultController < ApplicationController
def index
raise "FAIL"
end
def rescue_action(exception)
respond_to do |format|
format.html { render :text => "Rescued HTML" }
format.js { render :action => "errors" }
end
end
end
I solved a similar problem with authorization. I created a simple authorization controller with this action:
def unauthorizedxhr
render :update do |page|
page.replace_html("notice", :partial=>"unauthorizedxhr")
page.show("notice")
end
end
Here's the template:
<% if flash[:notice] -%>
<div id="noticexhr"><%= flash[:notice] %></div>
<% end -%>
When the authorization failed in the controller, I'd redirect to the :controller=>"authorization", :action=>"unauthorizedxhr" after setting the flash[:notice] value. This allowed me to customize the message I sent to the user, and it handled the display of the message through the render :update code above.
You could adapt this to your problem by creating an errors controller, catching any raised errors in your other controllers, then simply redirecting to :controller=>"errors", :action=>"displayxhr" when the call fails. That way, you'll have standardized your error communication mechanism but allowed yourself the ability to customize error messages by each action.
You can still use cpm's idea above, but the error's display will be handled by separate and distinct controller logic. that should make it a little easier to maintain.
Hope that helps.
-Chris
This was my final solution:
def rescue_action_in_public(exception)
response_code = response_code_for_rescue(exception)
status = interpret_status(response_code)
respond_to do |format|
format.html { render_optional_error_file response_code}
format.js { render :update, :status => status do |page| page.redirect_to(:url => error_page_url(status)) end}
end
end
This basically forwards to the correct static HTML page no matter if the request was via AJAX or normal GET/POST.
This is NOT used for normal error handling like validation etc. It's only used when something really bad happens - like an unhandled exception.
You can do like below :
in allpication.js
$(document).ready(function(){
$(document).ajaxError( function(e, xhr, options){
if("500" == xhr.status)
{
$(location).attr('href','/users/sign_in');
}
});
})
Its working for me.....

Resources