I am using devise for user registrations. I set up a custom edit page '/info' to use as an additional signup page. The only problem is after you submit the edits on the info page it redirects to the user profile. I am able to change it redirect to the home page (where I want after /info) but then it also redirects there from the normal edit page. I am not sure how to redirect based on what page the user is on.
My one idea was to get the users current path and use an if statement but I haven't been able to get that to work.
registrations_controller.rb:
def update
...
current_uri = request.env['PATH_INFO']
if current_uri == '/info'
redirect_to root_path, notice: "Welcome"
else
redirect_to user_path(#user)
end
end
Normally it just looks like this:
def update
...
redirect_to user_path(#user)
end
The problem seems to be you need to keep data around to determine where to redirect. A few ideas:
You could store data in the session when a user visits a previous page and check this data in your action to determine where to redirect the user. The session is often a convenient place to store things that are consistent between requests but that should not be persisted to the database.
You could store data in the database (for instance, add a flag to your user model) and check this to determine where to redirect.
You could check request.referer and redirect based on the value there. This may not be as reliable.
Related
I've followed the tutorial on the following article for how to deactivate users:
https://github.com/plataformatec/devise/wiki/How-to:-Soft-delete-a-user-when-user-deletes-account
My question is, how do I make it so that when a deactivated user signs in, it shows them a page that allows the to reactivate their account? IE: "users/reactivate" with a button to reactivate?
I know I have to rewrite the default Users sessions controller of course, but I'm not quite sure at what point or how active_for_authentication is called, and how I can overwrite the redirect.
When a user attempts to log in, the request is routed to the create method of your sessions_controller.rb, where a session for this user is created if credentials are valid. Within that method, you just need to check whether the deleted_atcolumn is populated, followed by some branching logic to either redirect to whatever landing page you have for valid logins or your reactivation page.
Your code would look something like the following sample, but again, you didn't provide implementation details, so it falls to you to adapt:
def create
user = User.find_by(email: params[:session][:email].downcase)
if user && user.authenticate(params[:session][:password])
unless user.deleted_at.nil?
my_user_login_method
redirect_to user # or redirect to a dashboard/landing page/whatever
else
render 'reactivate' # this would be a view for your reactivation page
end
else
flash.now[:danger] = 'Invalid email/password combination'
render 'new'
end
end
I have implemented redirect_to_back method in my ApplicationController for users that are not signed in (from this blogpost:
def redirect_to_back_or_default(default = root_url)
if request.env["HTTP_REFERER"].present? and request.env["HTTP_REFERER"] != request.env["REQUEST_URI"]
redirect_to :back
else
redirect_to dashboard_url
end
end
and I'm using in sessions_controller#create:
if #user && #user.authenticate(params[:password])
sign_in(#user)
redirect_to_back_or_default(dashboard_url)
else
...
The problem is, this only works if the request is coming from the application and not if it is a direct link, like in an email.
Is there a solution for this?
I would recommend altering how you accomplish this. If you follow the flow below I think it will produce the results you're looking for:
User arrives at URL (either by clicking link in email or typing it or whatever) but is not yet authenticated.
Store the URL that the user is at in the session
Redirect to the sign-in controller/action
After authenticating the user look in the session for where you stored the arrival URL
If present redirect to that URL (and clear stored URL out of the session) otherwise redirect to dashboard_url (it won't be present if someone navigates directly to the sign-in controller/action).
I am using Omniauth to make users sign up with Facebook account. When they first click on the auth link, I direct them to the sign up page for them to put some additional information, unless they already have an account for my application.
SessionsController
def create_facebook
#make an environment variable
auth = request.env['omniauth.auth']
if User.find_by_provider_and_uid(auth["provider"], auth["uid"])
user = User.find_by_provider_and_uid(auth["provider"], auth["uid"])
session[:user_id] = user.id
redirect_to lessons_path, flash[:notice] => "Signed in!"
else
#go to signup page to get additional info
redirect_to new_user_path(:auth => auth) #problem
end
end
In this case, I'm passing the entire auth hash using a parameter in the URL because I want to call User.create_with_omniauth(auth) in Users#new. Should I avoid from doing it? What are the other alternatives?
You've got a few approaches that I can see:
Store the auth value in the user's session (but bear in mind that the session doesn't encrypt values by default; it only signs them), and then pull them out when viewing the new user action.
Alternatively:
Just call the new user action code directly (either share it via a helper, or if it's on the same controller - call the action and then make sure you call render to set up the correct view)
A third and more robust alternative that is similar to the session approach, but a little more heavyweight:
Set up the user with what information you have at this step (and set them to some sort of "partially registered" state). Sign them in. Then make sure you read in any existing data when viewing the new_user action. Might also want to set up your routing layer to always redirect users in this state to the sign up page no matter where they are.
This is probably a fairly simple thing to do - I have a site with a news feed that shows various posts. There are also other pages that similarly show posts. Comments can be added to these posts directly from any of these pages.
What I need to do is redirect the user back to the URL they came from, once they've added a comment, and to the particular post they commented on (each post has an id of post-#{post.id}, so I'd just have to stick #post-2 or whatever to the URL.
If the post could not be saved, for whatever reason, I'd also like to have the content that the user had submitted pre-filled into the comment box after the redirect.
How can I do these two things? The first is the more important one..
I'd have to store the URL that the user is coming from in the session on the new action and redirect to this on the create action? How can I get the URL?
I'm on Rails 3.1 by the way.
Thanks for the help!
You could use redirect :back which will send the user back to the page that issued the request
redirect_to :back
Assuming Comment is a resource nested under Post in your routing (/posts/123/comment/new):
def create
comment = Comment.new(params[:comment])
if comment.save
redirect_to post_path(comment.post)
else
redirect_to new_post_comment_path(params)
# or maybe you have the comment form on the Post#show page
# redirect_to post_path(params)
end
end
Context
I'm building a super simple, knock-your-socks-off sexy sign-up page at http://hivechatter.com. (Yes, I feel strongly about her.)
The root page is the new user action, where I ask for email only. If the visitor submits a valid email, a new user is created and I redirect to that user's edit page and ask for additional, optional info.
Problem
The edit page url is of the usual form: http://hivechatter.com/users/19/edit. One can visit any user's edit page by simply visiting this url with whichever id number they choose.
Question
How do I restrict access to the edit user page so that it can only be visited once, and only immediately after having created that user_id from the root new user page?
I can think of a variety of methods to explore. I'd appreciate a pointer on the most elegant, rails way to do this. Note that I don't need any additional functionality like sessions, etc. This two step sign-up process is the extent of what I need right now.
Thanks!
Add new column to your users table. Let it be opened_once:boolean with DEFAULT false
Then in your users_controller
def edit
#user = User.find( params[:id], :conditions => ['opened_once => ?', false] ) rescue ActiveRecord::RecordNotFound
#user.update_attribute :opened_once, true
...
end
so now it can be showed only once right after creating new user when you redirect to edit page
UPD
What you can do more Rails way? Without adding new stuff to your database and so on. You can remove your edit action at all, so your edit view will rendered at create:
def create
#user = User.new params[:user]
respond_to do |format|
if #user.save
format.html{ render :action => :edit }
else
format.html{ render :action => :new }
end
end
end
User will see edit form only once if validation passed and his profile created.
So this is specific "Rails way" :)
The point of a cookie is to maintain state in the form of a session. HTTP by spec is stateless, and there for if you have people logging in then they need a session. RoR has a great session handler, I recommend using it.
The only other way to restrict access would be using a .htaccess file or similar method of doing basic-auth. This doesn't scale well and is less secure.