How do I Get the current user id in my controller using devise?
In my controller I have something like this:
def index
me = current_user
c = User.find(me)
#sheets = c.time_sheets
end
I am getting an error say that "Couldn't find User without an ID".
If If I put in a static number in the User.find() it works but of course that is not what I want. Any help would be greatly appreciated.
thanks!
Replace current index action as below
def index
if current_user
#sheets = current_user.time_sheets
else
redirect_to new_user_session_path, notice: 'You are not logged in.'
end
end
If user is not logged in, i.e., current_user=nil then user would be redirected to login page with a flash message.
Related
I am new to rails and have a task that asks me to send an invitation for any user to be admin in my magazine here is my piece of code
def invite
inviteUser = { 'user_id' => current_user.id, 'Magazine_id' => params[:id] }
CollaborationInvitation.create(inviteUser)
#magazine = Magazine.find(params[:id])
redirect_to :back
rescue ActionController::RedirectBackError
redirect_to root_path
end
I need to replace current_user.id with something that refers to any user's id which exists in my database to send him an invitation to be admin with me I tried to add #User=Users.All and then pass it as a variable but it got me an error I tried a lot of things but every time I get an error except for adding current_user.id
ps: I am using devise for authentication
You asked a couple things, and it is kind of confusing what you want to do.
Here is how you get all ids of records in a model.
Rails4: User.ids
Rails3: User.all.map(&:id)
Or (not sure if #pluck is in Rails 3 or not)
User.pluck(:id)
If you want to get a random user (you mentioned "any user") you could do.
User.find(User.pluck(:id).sample)
Though I think what you really want to do is to pass the id or some other attribute of a user as a param to the action and send that user an invitation.
Presumably you either have a post or get route for "users#invite" (the action you wrote in your question). You can add a named parameter there or you can pass a url param or if you are using a post route, you could add the param to the post body.
Then in your contoller you can do something like this (I'll use email as an attribute):
def invite
#user = User.find_by(email: params[:user_email])
#Rails 3 like this
# #user = User.find_by_email(params[:user_email])
# now do stuff with user
end
User.all will return you the collection of users. So,
Find the user object to get an id...
Try this code....
def invite
inviteUser = { 'user_id' => User.find_by_email('user#example.com').id, 'Magazine_id' => params[:id] }
CollaborationInvitation.create(inviteUser)
#magazine = Magazine.find(params[:id])
redirect_to :back
rescue ActionController::RedirectBackError
redirect_to root_path
end
You can try
User.last.id
or
User.find_by_email("xyz#test.com").id
or
User.where(email: "xyz#test.com").first.id
Replace xyz#test.com with desired user email address. To get more details on rails active record query interface, please read rails guides http://guides.rubyonrails.org/active_record_querying.html
In my application I am trying to enforce that users be signed in to preform certain actions. And when they try to preform these actions when not signed, they are redirected to the 'Sign-In' page, and once they have signed in, they are redirected back to the page they were trying to access. I have all of this working properly with the below code.
Controllers Code
if !(signed_in?)
session[:return_to] = newcompany_path
redirect_to signin_path
flash[:notice] = "You must be signed in to add companies."
else
#company = Company.new
#primary_field = ##fields
end
...
redirect_path = session[:return_to]
if user && user.authenticate(params[:session][:password])
sign_in user
session[:return_to] = nil
if (redirect_path == nil)
redirect_to user
else
redirect_to redirect_path
end
else
The issue I am running into is, if the user clicks away from the sign-in page without actually signing in, the session[return_to] variable is not cleared properly, and if they then go back to sign in later, they are redirected to the wrong page.
So, how would I set it up so if the user clicks away from the sign-in page, the session[:redirect_to] variable is reset?
You could pass the return_to path in query string parameter rather than the session and submit it alongside the sign in form so that it only applies for that form, rather than subsequent requests.
When redirecting to the sign in form, it'd look like:
redirect_to signin_path(return_to: newcompany_path)
Then, in your sign in form, make sure to include a hidden field with the return_to value, like:
hidden_field_tag :return_to, params[:return_to]
Then in your controller action for signing in, you'll check params[:return_to] rather than session[:return_to] to get the path you want.
Is this what you're looking for?
redirect_to request.referrer
I'm trying to let users submit a reservation request without being logged in. After they submit unauthed users are prompted to sign in or sign up. After signing up I'd like the form to be submitted and the (new registered) users to be taken to the checkout page.
Store location keeps the last page to return users after logging in. I need to figure out how to continue users on their intended path by submitting their forms and placing them on the checkout page after sign up/ sign in.
def store_location
#stores the last url. Used for post-login redirects to what the user was trying to do last.
if (!request.fullpath.match("/users/") && !request.xhr?) # don't store ajax calls
session[:previous_url] = request.fullpath
end
end
Ok, I think this is pretty dirty but I haven't been able to find another way to do this.
after_sign_in_path_for is a method Devise calls that allows you to send people to different pages after sign in.
I took all the create logic out of the controller and put it into a service object.
def after_sign_in_path_for(resource)
if session[:booking_params].present?
#booking = Booking::CreateBooking.new(user:current_user, params: session[:booking_params]).return_booking
checkout_booking_path(#booking.public_id)
else
session[:previous_url] || root_path
end
end
In the controller, the create method is split into two parts. If there is no current user I save their params into the session and they are sent to login. If there is the CreateBooking service object is called normally.
def create
if current_user.nil?
session[:booking_params] = params
redirect_to new_user_registration_path
else
#booking = Booking::CreateBooking.new(user:current_user, params:params).return_booking
respond_to do |format|
format.html { redirect_to checkout_booking_path(#booking.public_id) }
end
end
end
In the after_sign_in_path_for method I check for the session params and create the booking there.
Let me know if there is a better way to do this!
I have been trying to solve the following problem for a couple of days. Forgive me if this is a common problem as I am new to rails and probably couldn't query the right question/keyword in stackoverflow or google.
I am building a system where a user will get an invite via email, click on a unique link, be taken to a page where he/she can accept or decline the invitation. I am getting stuck at the part where the user accepts or declines the invitation.
I've built it around two controllers: an invitations controller and a confirmations controller.The invitations controller creates a record containing a name, an email, and a uniquely generated token. The controller then emails a link with the token to the defined email. The link points to the confirmations controller and passes the unique token from the invitation. However, when clicking on the link and accepting the invitation, I get the following error:
NoMethodError in ConfirmationController#confirm
undefined method `update_attribute' for nil:NilClass
Here is some of the code for solving this issue:
Confirmation_controller.rb
class ConfirmationController < ApplicationController
def new
#confirmation = Invitation.find_by_invite_token(params[:invite_token])
end
def confirm
if #confirmation.update_attribute(:accepted, true)
flash[:success] = "Invitation confirmed!"
redirect_to 'static_pages/home'
else
flash[:notice] = "Failed :("
redirect_to 'static_pages/home'
end
end
end
routes.rb
match '/confirmation/:invite_token', to: 'confirmation#new'
match '/confirmation/:invite_token/confirm', to: 'confirmation#confirm'
app/views/confirmation/new.html.erb
Click here to accept:
<%= link_to "Confirm", :controller => "confirmation", :action => "confirm" %>
You need to get your Invitation in the confirm method too.
If you want rails to raise an exception if no invitation was found
def confirm
#confirmation = Invitation.find_by_invite_token!(params[:invite_token])
#confirmation.update_...
end
No exception will be raise. You may want to check manually with a condition in the following case.
def confirm
#confirmation = Invitation.find_by_invite_token(params[:invite_token])
if #confirmation
#confirmation.update_...
else
# do something
end
end
You should find confirmation record before calling update_attribute on it, like you did it in new action:
#confirmation = Invitation.find_by_invite_token(params[:invite_token])
Or, to throw exception when the record is not found and to render 404 page to the user:
#ocnfirmation = Invitation.find_by_invite_token!(params[:invite_token])
The problem is that you never told the program what #confirmation is. What you should do is find it first then run the update. Note this is different from the different answers, just thought I would throw in some variety.
def confirm
# You're missing this line below. Basic search for the confirmation.
# Note too that you will have to pass in the parameter `invite_token` for it to work
# I'm also assuming invite_token is unique among each invitation
confirmation = Invitation.where(invite_token: params[:invite_token])
# Notice that I'm first checking to see if the confirmation record exists, then doing an update
if confirmation and confirmation.update_attribute(:accepted, true)
flash[:success] = "Invitation confirmed!"
redirect_to 'static_pages/home'
else
flash[:notice] = "Failed :("
redirect_to 'static_pages/home'
end
end
In my application I have a user confirmation process. When a user signs up four things happen:
An account_status_id is set to 1 (unconfirmed)
The user is signed in (now current_user exists)
A new_account_confirmation_token is generated
A confirmation email is sent to the new user with a link that includes the new_account_confirmation_token
I initially tried to handle the confirmation link with this method. It finds the user without issue and the code flows through the update_attributes! method, however it wasn't updating the account_status. From what I can tell it is due to the fact that the current_user object exists, therefore the user Im trying to update is already "in memory". Is that correct?
def new_account_confirmation
#title = "Account Confirmation"
logger.info("User is not logged in")
#user = User.find_by_new_account_confirmation_token(params[:confirm_id])
if #user
#user.update_attributes!(:account_status_id => 2)
else
redirect_to root_path
end
end
My work around is as follows. The code below works but I'd like to know why the code above doesn't work. Why won't it update the account_status?
def new_account_confirmation
#title = "Account Confirmation"
if current_user
logger.info("User is logged in")
current_user.update_attributes!(:account_status_id => 2)
else
logger.info("User is not logged in")
#user = User.find_by_new_account_confirmation_token(params[:confirm_id])
if #user
#user.update_attributes!(:account_status_id => 2)
else
redirect_to root_path
end
end
end
Even if your user is "in memory" as you say, that's no reason for it not to update. I believe your update IS happening but you're just not seeing it because current_user is not in sync with #user.
I don't know how you're verifying that #user is not being updated but if update_attributes! is not throwing an error then it's being saved.