Rails Redirect Not Going as HTML - javascript

I have a sign up form that should redirect the user to their profile if sign up is successful. If registration fails I want to put up an error message without reloading the page using Javascript.
Here's my form header:
<%= form_for resource, as: resource_name, url: registration_path(resource_name), remote: true do |f| %>
My registration controller:
def create
respond_to do |format|
if resource.saved
sign_up(resource_name, resource)
format.html { redirect_to current_employer }
else
format.js { render 'employers/sign_up_failure' }
end
end
end
So the failure works. It displays an error message above the form without reloading the page.
The successful registration format.html { redirect_to current_employer } is not working.
My server log says the redirect was handled:
Redirected to http://localhost:3000/employers/27
But it looks like the show action on my Employers controller is being called as Javascript:
Processing by EmployersController#show as JS
So when I submit the form, it does not redirect me to my profile page. The page doesn't flicker. I am logged in though, so if I refresh the page it shows that I am logged in.
BTW, I am using Devise and my Registration controller is an amendment to what Devise uses.
Not sure why this isn't working. I've taken out the format.js {} part and it still sends the GET call to my Employers#Show action via JS. What I'd like is for the redirect to be formatted as HTML and take me to the profile page.
Any ideas?
SOLUTION
Thank you for you help. Face palm, I totally forgot about how remote: true works. Here is my implemented solution... hopefully someone finds this useful.
def create
respond_to do |format|
if resource.saved
sign_up(resource_name, resource)
#CHANGED
format.js { render js: "window.location.href = '/#{resource_name}s/#{resource.id}'" }
else
format.js { render "#{resource_name}s/sign_up_failure" }
end
end
end
This also improved the reusability of the code.

Because you have remote: true on the form it is submitted via ajax, you haven't said what to do if submitted via ajax and successful. The format requested is js not html which is why the redirect isn't working.
You'll need to create a create.js.erb file to serve if successful, handling the redirect through javascript with window.location = "wherever you want to go"

Related

format.js not executing (ajax)

I'm trying to add email confirmation when signing up users. Users have to fill out a form with their invitation code and email address, and then they get an email with an activation link.
So all I want to do is have it so when the user fills out the form, it submits the form and reloads the form so that it hides and displays the message "we sent you an email, please check and click the link" instead of reloading the entire page.
signup.html.erb
here I've added remote: true
<%= form_tag(form_action, method: :get, remote: true, id: 'create-form') do %>
users_controller.rb
the redirect works but format.js is an unknown format
def new
... code checking params
if #user.user_email_confirmed
render :new
else
respond_to do |format|
format.html { redirect_to signup_path(#user.name, email: #user.email) }
format.js
end
end
new.js.erb
$('#create-form').hide().after('');
$('.login-form').append('<p class="link-sent">We have sent an activation link to the email address you entered - please be sure to check your spam or trash folders. Please click that link to complete account activation.</p>');
not sure what I am missing, any ideas?
I really do not think that the action the form is calling when submitting is your new action, it may be some create action in your controller.
So when you hit the "submit" button of your form it is sent through Ajax due to you have remote: true option, and the action it is calling does not have a format.js nor js.erb view, That's why you get unknown format.
Make sure which controller action is being called when you submit your form, then add the format.js and the proper js.erb view.
Please take a look to this blog post, it may be helpful.

Rails responding to different formats with AJAX request

I'm trying to understand AJAX requests in Rails. I have a form that I currently submit using remote: true. I want to respond with an HTML redirect if the request is successful, and run an error message with Javascript if it is unsuccessful. However, no matter what the outcome is, the request seems to expect a .html as the return.
respond_to do |format|
if conversation
format.html { redirect_to(conversation_path(conversation)) }
else
format.js
end
end
This is called after I save the conversation call on AJAX. On a successful save, the path HTML is correctly sent back, but is not rendered on the client. But on an unsuccessful save, it expects the .html and throws an error. How do I accept .js as a response? My goal is to just pop up an error if the call is unsuccessful and redirect_to on a successful call.
Edit: My form_for:
<%= form_for :conversation, url: :conversations, remote: true, html: { class: "conversation-form" } do |f| %>
Here's a suggested alternative to your end-goal - in the controller, drop the format.html entry in your respond_to block. Also, set conversation to an instance variable that the view template can access:
class YourController < ActionController::Base
def your_action
# awesome code doing stuff with a conversation object goes here
#conversation = conversation
respond_to do |format|
format.js # your_action.js.erb
end
end
end
Then, put the redirect logic in your javascript view template (for the above example: app/views/.../your_action.js.erb):
<% if #conversation.errors.any? # or whatever condition you want to show a popup for %>
// put your javascript popup code here
alert('Errors happened!');
<% else %>
// this is how you do a redirect using javascript:
window.location.href = "<%= conversation_path( #conversation ) %>";
<% end %>
Hope this helps!

how to have an application helper method work when the sent request is JS formatted?

I have a signed_in? method in rails that will drive u back to the landing page if you have been inactive for 5 minutes.
How do I make this work when the user clicks on a form submitted via js after the 5 minutes have passed? Obviously when this happens, the server sends the landing page back to the user, but it is not shown. Here is my signed_in method
def signed_in?
unless current_user
flash[:notice] = "Please log in"
redirect_to root_url
else
if session[:expiry_time].nil? || session[:expiry_time] < 5.minutes.ago
reset_session
flash[:notice] = "Please log in"
redirect_to root_url
else
session[:expiry_time] = 300.seconds.from_now
end
end
end
PS: I know it's horrible code, I'll be sure to refactor it :)
But I'd start by implementing an alternate redirect method that does a full redirect even for XHR requests:
def redirect_with_js location
if request.xhr?
# HTML response is expected:
render :text => "<script>document.location = '#{view_context.escape_javascript location}'</script>"
# JS response is expected:
# render :text => "document.location = '#{view_context.escape_javascript location}'"
else
redirect_to location
end
end
Then use this method when redirecting:
redirect_with_js boomeranked_url
The returned text depends on what type of response the AJAX request expects to get back (HTML or JS). I've included both versions. This should give you something to start with.
This is the solution I came up with it, I find it simpler. In the signed_in method:
respond_to do |format|
format.js {
flash[:notice] = "Please log in"
render 'home/not_logged_in'
}
And then on the not_logged_in view
window.location = '<%= root_url %>';

How can I stop the js response from being executed?

I am using Rails3.1 + Jquery. I have two forms that submit "update" requests to the same controller. For one, I would like to display an alert to the users to tell them whether the request was successful. The other should be quiet. My controller code looks like this:
respond_to do |format|
if #user.update_attributes(params[:user])
format.html { redirect_to #user, :notice => 'Settings were successfully updated.' }
format.json { head :ok }
format.js { flash[:notice] = 'Settings were successfully updated.' }
...
The update.js is responsible for updating the flash div with the flash message. That works great. The problem is that this happens even from the form that I want to be silent. I'd like to modify the form itself to ignore any javascript in the response. I am having trouble finding anything in the Rails guides or through Google.
You can also solve this using js, set a variable called caller which holds the value of the calling form, after getting ajax response check if caller is form1 show message else return;
pseudo code:
var caller;
//In ajax response
if (caller==1) {
//show message
} else {
return;
}

Can I redirect_to a javascript request to another javascript action?

I have a comments controller with index and create actions among others. Both those actions respond to html and js format.
Whenever I got create request via ajax, I would like to add new comment and then redirect to index.js, so the comments on screen are updated without reloading the page.
This sort of thing works flawlesly in Chrome. But whenever I try this in Firefox or IE, it turns out, that the redirect from create.js lands in index.html...
Even when i force the redirect to be js:
redirect_to polymorphic_path([#commentable, :comments]), :format => 'js'
It land up in the format.html in Firefox and IE.
Any idea what might be happening here?
There are various issues with the way browsers handle 302 requests differently. Some lose request types, others lose request method (an example ticket: http://trac.tools.ietf.org/wg/httpbis/trac/ticket/160).
I would suggest that rather than redirecting to a new URL when using JS, you simply render the same action. So something like this:
class CommentsController < ApplicationController
def index
setup_for_index
respond_to :html, :js
end
def create
# Creation stuff...
respond_to do |format|
format.html {redirect_to :action => :index}
format.js do
setup_for_index
render :action => :index
end
end
end
private
def setup_for_index
#comments = ...
end
end

Categories

Resources