current_user returns nil even when user_signed_in? returns true - ruby-on-rails

I have devise 2.1.2 and cancan 1.6.8 installed.
The current_user helper from devise works fine in my controllers, but is not working the view templates. I'm confused why this is happening. I've been able to use current_user in my view files before.
I tried adding the before_filter authenticate_user! and that didn't help.
Worse comes to worse, I'll add a before filter to the application_controller that says #current_user = current_user but that seems silly.
It's weird that current_user returns nil while user_signed_in? returns true.
Any thoughts on how to get this resolved?

In the meantime,warden.authenticate(:scope => :user) seems to return the current_user so I'm just going to add that to my application helper.

Related

devise rails current_user vs user_signed_in?

I am using Devise on Rails 4.1
My question is regarding the helpers and how they relate to sessions.
current_user : tells you if there is a user session available for the user.
user_signed_in: tells you if the user is authenticated.
I cannot understand how a there can be a current_user if the user_signed_in? is false?
What is the difference between the two methods, and how does it relate to sessions.
THanks.
Richard Madson
user_signed_in? is provided as a convenience. You are correct in your assertion that if user_signed_in? is false, there will never be a current_user.
In the devise source code, we can see:
def #{mapping}_signed_in?
!!current_#{mapping}
end
(where user takes the place of #{mapping})
user_signed_in? simply returns the truthiness of current_user, ie, false if current_user is nil.
current_user method returns current signed-in user, while user_signed_in? method is used to verify if any user is signed in and returns true or false. if user_signed_in? is false then current_user method will return nil.
https://github.com/plataformatec/devise#controller-filters-and-helpers

Session Helper Methods in Michael Hartl Tutorial Chapter 8

I'm going through Michael Hartl tutorial on Ruby on Rails and I'm having trouble understanding some logic. Note that the logic works, it's just not resonating with me on what's actually happening.
In this chapter we're logging in users and creating a session. Here the helper methods:
module SessionsHelper
# Logs in the given user.
def log_in(user)
session[:user_id] = user.id
end
# Returns the current logged-in user (if any).
def current_user
#current_user ||= User.find_by(id: session[:user_id])
end
# Returns true if the user is logged in, false otherwise.
def logged_in?
!current_user.nil?
end
end
Depending on whether the user's logged on or not we change the navigation with this conditional:
<% if logged_in? %>
do something....
<% else %>
do something else...
<% end %>
As I understand it, the code checks to see if the user is logged in by calling the logged_in? method. The logged_in? method calls the current_user method to see if it's nil. If it is nil it returns false, if it's not nil it returns true. As a test I tried to change the logged_in? method to the following:
def logged_in?
!#current_user.nil?
end
When I run this method for some reason, after I log in with credentials that are authenticated, #current_user returns nil. Why is this? Note this works if I change it back to the original logged_in? method where I'm just calling the method current_user.
This is not a direct answer to your question since you have that figured it out while I was trying to answer. But I want to clarify on some points.
In rails, in fact most of the web application, we track a user's log in state in server's session. the log_in method in your code does that.
Then when the new request comes in to a controller that requires authentication, we check the session if there is a stored user. If it exists then the request is authenticated, else it's unauthenticated. So, logged_in? method's actual responsibility is to check the session.
However, it is quite common that we want to access the authenticated user's attributes in the controller and/or views. So we set an #current_user variable on the controller so that you can access the User object of authenticated user. Again, using an instance variable directly is not a good practice. So we wrapped it in the current_user method.
Then you might ask, why don't we store the whole user object in session? Because it is bad to store much in session(see here). So, we just store the id and use it to get the user from db.
Here is where the ||= part comes in. ||= caches the result of db. Otherwise, we would be hitting db every time we call current_user method.
Hope this clarifies a bit on what's actually happening.
As I was formulating my question I figured this out. In the later case
def logged_in?
!#current_user.nil?
end
#current_user isn't set yet because the current_user method was never called. To test, I changed the method to the following:
def logged_in?
current_user
!#current_user.nil?
end
where the method was called first and then #current_user was evaluated. It worked without issue. The original method works because current_user returns #current_user to the logged_in? method as either a user object or nil (#current_user is set as the last line in the method -- it's the only line, so it's retuned implicitly to the logged_in? method).

undefined method `update_attribute' for nil:NilClass, signing out

I have been stuck on this problem for a while, but still can't figure out what the problem is
def sign_out
#return unless signed_in? # you are already signed out
current_user.update_attribute(:remember_token,User.digest(User.new_remember_token))
cookies.delete(:remember_token)
self.current_user = nil
end
rails returns me a error on #current_user, saying the update attribute undefined?
As far as i understand, my current user is already defined by this method
def current_user
remember_token = User.digest(cookies[:remember_token])
current_user ||= User.find_by(remember_token: remember_token)
end
Am i missing something here? I'm following the rails tutorials if it helps, but I kind of strayed off and added a additional page after the user creates a profile..... but I'm sure its ok because i saved the #user by doing
User.find(params[:id])
Or can someone explain to me the error in better detail?
Thank you
The method current_user will define the #current_user instance variable, but this is for it's own purposes - to stop it having to do a db query every time it's called.
You can access #current_user in your own code, but it won't exist if current_user hasn't been called yet, and will therefore evaluate to nil.
It's therefore safer to always use current_user and never use #current_user.
Can someone explain to me the error in better detail?
--
current_user
update_attribute' for nil:NilClass
This error is nothing to do with update_attribute, and everything to do with the object you're trying to call the method on - in your case current_user (basically means current_user is not defined)
The answers & comments you've been given basically are trying to help define the object you're calling the method on - I.E that current_user needs to be defined somewhere
From looking at your code, there are two things you need to consider:
Is current_user method being created / called?
Is the correct object being defined in this method?
--
Data
You've provided the following method:
def current_user
remember_token = User.digest(cookies[:remember_token])
current_user ||= User.find_by(remember_token: remember_token)
end
As pointed out by sevenseacat, the first thing I would do is ensure you've got a user who can be located with the remember_token. An important point actually - what's .digest?. Is it a class method in your model?
The likely problem you've got is trying to use the User.digest and User.find_by with the remember_token. Do you know where / how the remember_token will be set?
--
Method
Secondly, you need to make sure you're calling the current_user method. I'm guessing this is a helper method? If so, are you sure you're calling include xxxHelper in your controller?
never mind, found the bug.Had some unwanted code in my application controller

Rapidfire and Devise

I implemented Devise and went through the instructions to install Rapidfire
and for the application controller I have
def current_user
current_user #rb:7
end
def can_administer
true # just for right now...
end
but on the page I get a something went wrong and if I look in the console it says
ActionView::Template::Error (stack level too deep)
app/controllers/application_controller.rb:7
which is the current_user line.
Can anyone tell me whats going on?
You are creating a method called current_user, and you are returning the value of current_user.
Ruby doesn't require that you use parenthesis when calling methods.
current_user
is the same thing as
current_user()
You are calling the current_user function over and over and over again.
There is no reason for you to define a method called current_user, when devise gives that to you.

What is the difference between current_user and #current_user (I am using devise) ?

I know #current_user is instance variable but I am still unclear about the difference between current_user and #current_user ? when should i use current_user and when #current_user ?
In my personal experience with devise I never use #current_user, current_user always suffices wherever and whenever I want.
The official documentation only mentions current_user too.
Devise Controllers filters and helpers
current_user is the helper method provided by devise to access the current user. There is nothing like #current_user from devise unless you have set it in your code.

Resources