How to make devise gem go to specific page when the option 'Remember me' is ticked? - ruby-on-rails

So, a returning user in my app who has ticked "Remember me" has to land in a different page inside the app instrad of the home page and being logged in there.
I went through the documentation but i cant find a function that does this.
I also struggle into make devise go to a different page when the user updates the profile and i use wrong methods for this. Can you give me the correct method and where to put it as well?
I tried using the method 'after_remembered' in my ApplicationController but it doesn't work while the method after_sign_in_path_for works!
Do i need to overwrite something?

Devise sets a remember_created_at value for the user if "Remember Me?" is selected. In the after_sign_in_path_for you could have it check for resource.remember_created_at and then perform the redirect there.
A quick example would be in app/controllers/application_controller.rb
def after_sign_in_path_for(resource)
resource.remember_created_at ? path_for_remember : path_not_for_remember
end
To handle redirects after updates you want to use the after_update_path_for which is set up the same way:
def after_update_path_for(resource)
some_path
end

Related

How do you make sure that after sign in the user completes the profile form first before they can use the rest of the website functions.

How do you make sure that after sign in the user completes the profile form first before they can use the rest of the website functions. I am trying to make sure that after the member has completed the sign up form and then completes there email confirmation with devise that when they sign in that when they are redirected to the new_member_profile_path(current_member) form that they stay on this page and that if they decide to go to a link and click that that they will automatically be redirected back to the complete your profile page with the notice before please complete your profile first. I have it set already once they have completed the form they will be redirected to their member's page. I have looked in multi-forms with wicked - I really feel that because I am still am a Novice rails developer that this would be unnecessary. I am thinking about putting an if clause in the application.html.erb where the site nav template is based and putting a clause with <% if current_member_profile.blank ? %> then redirect back to new_member_profile_path(current_member) with a flash notice tag written in the html file. I have tried this if clause but does not work - comes up as undefined method. Please could someone point me in the right direction or give me the simple solution of getting this idea to work. Thanks in advance ;)
There are various approaches to achieve what you're trying to do. Perhaps the cleanest with the least amount of code needed would be to first authenticate the user with Devise's own authenticate_user! filter and then check for a field that can only be there when the profile has been filled in.
# in user.rb
def has_completed_profile?
first_name.present?
end
# in application_controller.rb
before_action :authenticate_user!
before_action :require_user_profile
private
def require_user_profile
# nothing needs to be done if the profile was already filled in
return if user_signed_in? && current_user.has_completed_profile?
redirect_to edit_profile_url, alert: "Please complete your profile first!"
return false
end
Notice how I've extracted has_completed_profile? into the User model instead of putting the name check directly into the controller. This way, if you need to change the logic of what makes a profile "complete", you don't need to touch the controller at all ("complete profile" is a business concept, not a routing/HTTP concept and thus doesn't belong in the controller).
In controllers where you don't want the additional profile check – e.g. the controller where the user actually completes their profile, where they presumably need to be logged in but can't have a profile yet – you just skip the additional filter:
# in profiles_controller.rb
skip_before_action :require_user_profile
Side note: Over the years I've learned that it's best to keep things like profile data, address data, phone numbers and what not in a separate model and don't extend Devise's User model. This prevents various issues and keeps the already huge User model (Devise includes dozens of methods into it and turns it into a God Object as it is) a bit slimmer. And if you think about it, it also makes sense in terms of business logic: A user has_one profile, has_one address (or has_many addresses) etc.
Hope that's clear.
You can add a new method in the application_controller.rb
For eg
def current_member_profile
current_user.name.blank?
end
Check the params which should not be blank when creating a member profile. I have added 'name' here for example. if the params is blank, then it will redirect as you have specified in your application.html.erb
Instead for putting an if condition on the application.html.erb, You can use a before_action in your application_controller.
Something like this.
application_controller.rb:
before_action :check_for_profile_completion
def check_for_profile_completion
// your code of redirection to the page if the profile is incomplete
end
Also you can skip this action on controller which you don't wanna restrict user to go. Like
skip_before_action :check_for_profile_completion, only: [://actions you wanna skip seperated by comma]

Devise - override redirect for the custom login page

I have the following interesting problem. I've created a secondary login form. From that secondary form I want the user always to be redirected to the specific form. I believe Devise is handling redirects in the following function in ApplicationController:
def after_sign_in_path_for(resource)
# custom redirect stuff
end
What would be the best way to tell devise "if I am coming from the custom redirect path, always take me to some specific page and disregard what ever is in params[:redirect]". I was thinking of either inspecting referrer url string or storing stuff on the session, but I am not sure.
What would be the best way to achieve this behaviour? Any suggestions would be appreciated!
Inspecting Devise code, I found that it is possible by clearing out the session variable where Devise stores the return path:
session[:user_return_to] = nil # or some explicit path
Note: Assuming the authenticated model is user.rb

authenticate_user! from Devise, in spree (spree commerce), does not work as expected when used as a before_filter

I am using Rails (3.2.6) with devise (2.1.2) and have a controller where I would like to make sure users are authenticated before proceeding.
Optimistically, I tried...
module Spree
class MyAppController < Spree::BaseController
before_filter :authenticate_user!
...remainder of MyAppController code...
and I am NOT redirected to a login or sign-in page. I am redirected to the 'products' page, with a polite message at the top saying I need to sign-in or sign-up to continue.
What I would like to happen is that I am redirected to sign-up / sign-in and when that is completed successfully, the original controller path resumes.
Searching around, I have read that authenticate_user! from Devise interacts with Spree in such a way as to cause an infinite redirection, so something in Spree disables this, resulting in the lame behavior I describe above.
Has anyone managed to get this to work or have suggestions for a good work-around?
I have found a work around, but I am not an experienced enough Rails developer to know how reasonable this solution is.
I wrote a method to do the filtering and used it instead of authenticate_user!...
def require_authentication
unless current_user
# setting this in the session allows devise to return us to
# the original invocation path, once sign up / sign in is complete
session[:user_return_to] = request.env['PATH_INFO']
redirect_to new_user_session_url and return
end
end
did you try adding
before_filter :check_authorization
to your controller?
I think that may do what your looking for.
Thanks
Ash

rails 3 / heroku / devise: how specify different 'landing page' when users sign in?

We'd like to have 3 different signin forms for our app:
the default signin form, takes them to their normal dashboard (as we do now)
a "foo" signin form that, if they use THAT form to sign in, takes them to a special purpose screen
a "bar" signin form that takes them to yet anogther special-purpose screen
I assume the right approach is to somehow
a) create a new route for /foo and /bar, probably directing both to the SAME signin method but in the route add a url parameter 'signin_type' telling us which "type" of signin form it is?
b) implement a custom RegistrationsController method(s) (what name?) to handle the signin form (we already have a custom new and create method for when they register, since our registration form needed a 'referral code' field added), and have the method look at the url parameter 'signin_type' to redirect the sign to either the normal, or foo, or bad
c) implement another method that handles the signin submit (is that a different method?) that looks at some special embedded form value to figur eout which signing form was used?
That's my best guess. If correct, it's how to do (b) and (c) that has me stumped. Any thoughts will be appreciated!
I think you may be trying to over engineer this. I would approach this with a single sign_in page, and just use conditional logic in overriding the after_sign_in_path_for(resource) method for the Devise controller. Not only will this be much easier to implement now, it will be a lot easier to maintain in the future. Simply add to your ApplicationController.rb:
protected
def stored_location_for(resource)
nil
end
def after_sign_in_path_for(resource)
if condition_foo
redirect_to foo_url
elsif condition bar
redirect_to bar_url
else
redirect_to dashboard_url
end
end
The first method overrides Devise's default location of root and sets it to nil, then the logic after that is pretty self explanatory. This should work for what you are wanting.

Is the user logged in? (restful-authentication)

I have used restful-authentication and I have "public" layout and a completely different "members" layout. When someone visits my root (defaults to public) how can I check if they are logged in and redirect them to the member's section?
RestfulAuthentication provides some conditional methods/helpers including one called logged_in?. It returns true if the user is logged in.
Check out the authenticated_system.rb file for the list of all available methods.
You could define a method like this in application_controller.rb:
private
def require_user
# logic to check if session exists and redirect if not
end
Then add the following in your pages that require that the user be logged in:
before_filter :require_user
I'm not familiar with restful-auth so I don't know the exact check that would be required.
Good luck.

Resources