tg_so
tg_so

Reputation: 496

Rails: redirect with call to Ajax

I'm trying to redirect un-logged-in users directly to a login window, which is a bootstrap modal window.

I wrote a method called logged_in_user in ApplicationController:

def logged_in_user
  unless !current_user.nil?
    flash[:danger] = "Please log in"
    redirect_to root_url
  end
end

The login_url routes to sessions#new, which I defined as below:

(sessions_controller.rb)

def new
  respond_to do |format|
    format.html
    format.js
  end
end

Here is the view that redirect_to root_url points to:

  <!-- Login Window -->
  <div id="login-window" class="modal fade" role="dialog" aria-labelledby="login" aria-hidden="true"></div>

Here is new.js.erb that gets executed when sessions#new is called:

$("#login-window").html("<%= escape_javascript(render 'sessions/new') %>");

Thus the login form, which is _new.html.erb in app/views/sessions, will appear as a popup window once the sessions#new is called.

Except that it has to be processed as JS rather than HTML. So I have the following link, which is in the _header.html.erb and available across all views, to ensure this is the case:

<%= link_to "Log in", login_path, {remote: true, 'data-toggle' =>  "modal", 'data-target' => '#login-window'} %>

This works fine when the link is clicked. This is why I chose to do redirect_to root_url rather than redirect_to login_url in logged_in_user method as the latter approach results in "Missing Template error".

But what I really want is for users to be redirected straight to the popup window, rather than them being redirected to root_url first and having to click "Login" link to enter the form. In other words, I need a way to somehow redirect users to the sessions#new by issuing an Ajax request so that sessions#new can be processed as JS.

I tried the following approaches for the desired redirect within logged_in_user method, none of which worked:

render js: "window.location = <%= escape_javascript(render 'sessions/new') %>"

render js: "window.location = '/sessions/new'"

redirect_to login_url, format: "js"

Any suggestions will be greatly appreciated!

Upvotes: 2

Views: 1013

Answers (2)

tg_so
tg_so

Reputation: 496

This issue was solved by modifying the following files:


(application_controller.rb)

def logged_in_user
  unless !current_user.nil?
    session[:modal] = true
    redirect_to !request.referrer.nil? ? (request.referer + "#login-window") : "#login-window" 
  end 
end

I've omitted flash[:danger] because it was shown "behind" the faded screen. I've added request.referer to make sure that the login popup window appears where the user has made a request, rather than redirecting them to root_path. I thought this would be better for user experience. (The ternary was just to handle the case where request.referer can be nil, in which case the code rases an error.) The motif behind session[:modal] = true is explained below.


(at the bottom of application.html.erb)

<% if session[:modal] == true %>
  <script type="text/javascript">
    $(document).ready(function() {
      if(window.location.href.indexOf('#login-window') != -1) {
        $('#login-window').modal('show');
        $("#login-window").html("<%= escape_javascript(render 'sessions/new') %>");
      }
    });
  </script>
  <% session[:modal] = false %>
<% end %>

Here I'm using javascript directly inside the view template. Since the view template upon which the popup window appears is not limited to one particular template, I've out the script inside application.html.erb, which applies to all view templates. The first half of it was inspired by cruncher 's answer. (Thank you cruncher!) I've then added $("#login-window").html("<%= escape_javascript(render 'sessions/new') %>"); to make sure that the login form (``app/views/sessions/_new.html.erb) does appear.

Now, since I want the login popup window to appear only when non-logged-in users try to access pages which require login, I went ahead and added session[:modal] = true to indicate that logged_in_user method was indeed called, which means that the above situation indeed occurred.

Then, inside application.html.erb I can check whether the popup window should appear by <% if session[:modal] == true %>. If that's the case, then the script will be executed, after which I set the value of session[:modal] to false.

This session[:modal] logic may not be necessary (in fact, it worked fine without it), but I've added it just in case.


That's it :)

Also, for those of you who want to implement this pop-up window functionality with bootstrap, here is a blog I've found really useful:

https://coderwall.com/p/ej0mhg/open-a-rails-form-with-twitter-bootstrap-modals

Happy coding!

Upvotes: 1

cruncher
cruncher

Reputation: 54

Just add this

<script type="text/javascript">
  $(document).ready(function() {

  if(window.location.href.indexOf('#login-window') != -1) {
    $('#login-window').modal('show');
  }

});

</script>

And

redirect_to root_url+"#login-window"

Upvotes: 1

Related Questions