How to define current_user in Devise? - ruby-on-rails

I want to print current user email in my RoR app. For this I did use the next code:
User.current_user
and it prints the next error: undefined methodcurrent_user' for #`
but when I used just current_user it doesn't print anything. I did search in Google and Stack, tried to use the answers of them, but nothing.
How can I get the user email?

In controllers, current_user alone will return the current signed in user. So current_user.email will return the email of the signed_in user. For non-signed in users, current_user will return nil.
To print the current user email in controller,
class TestController < ApplicationController
def example
p current_user.try(:email) # try is used because it will return nil if the user is signed in. otherwise, it will raise an error undefined method 'user' for nil class
end
end

Try this.
User.current_user.email

Related

Defining a method on current_user without it throwing a no method error on non logged in users

I made a moderator method thats in the user model
def mod_of_game?(guide_id)
game_mods_relationships.exists?(game_category_id: guide_id)
end
Problem is that whenever the user isn't logged in it just throws a no method error on the page.
I'll be making more user methods in the future and i can only assume i'll come across this problem every time.
I haven't tried it but i guess i could put an if else statement in the method
def mod_of_game?(guide_id)
if current_user.nil?
#empty method
else
game_mods_relationships.exists?(game_category_id: guide_id)
end
But I feel there is a more efficient way that i'm not aware of. I'm Building an app to learn rails better so i guess this is one of the things I just dont know.
The problem is that if no user is logged in, current_user will be nil, not an instance of the User class. So, there is no way to fix this inside the User model, as current_user is not a User if it is nil. Also, current_user is generally not available in the model, just in the controller and view.
What I would recommend is to add a filter in the controller, to make sure that if no user is logged in, the visitor will be redirected to the log in page. This can be done with a before_action filter in the controller, something like:
class YourController < ApplicationController
before_filter :authenticate_user!
...
end
Otherwise you can always check if current_user is nil before calling .mod_of_game?, like so:
current_user.mod_of_game?(#guide) unless current_user.nil?
Try following:
# It will return `nil` if user is not logged in
def mod_of_game?(guide_id)
game_mods_relationships.exists?(game_category_id: guide_id) if current_user
end
Your pattern is wrong.
Calling mod_of_game? is an instance method, which means it's got to be called on an instance of User.
By the nature of current_user, you wouldn't be able to call this method unless the user was logged in, or at least invoked.
You'll have to use all the conditions on the front-end to determine firstly whether current_user exists, and then to call mod_of_game? on it...
<% if user_signed_in? && current_user.mod_of_game?(#guide) %>
--
A much better way would be to either create your own helper method, or to use the .try method:
#app/helpers/application_helper.rb
class ApplicationHelper
def mod? guide
return false unless current_user
current_user.mod_of_game? guide
end
end
This would allow you to call:
<% if mod? #guide %>
... which will return false if the user is not signed in, or the user is not a mod.
The reason the pattern is bad is because you're having to base logic on two conditions: user signed in? AND are they a mod?
What you want is a single point of logic, which will return true or false:
<% if current_user.try(:mod_of_game?, #guide) %>

User can enter up to one room

I'm making chat. I want user not to enter more than 2 rooms at the same time.
So I made 'enter' model. This belongs_to users and rooms. User has_one enter and room has_many enters.
In the ApplicationController, there exists current_user.
def current_user
return unless session[:user_id]
#current_user ||= User.find(session[:user_id])
end
I tried to examine if user has a enter or not by following way.
def free?
return unless session[:user_id]
if current_user.enter.room.count == 1 then
return true
else
return false
end
end
This is in the ApplicationController, too.
Next, I wrote <% if logged_in? && free? %> in the views/top/index.html to display 'join this room' button for only logged in free user.
When I run this, I have following error.
NoMethodError at/ undefined method 'free?' for #<#<Class:...>...>
I couldn't solve this on my own... What should I do?
You can create free? method on user object.
class User
def free?
enter.room.count == 1
end
end
After that inside the view call this, current_user.free?
But will be better if you check if enter object exist with combination of this user and room.

undefined method `is_admin?' for nil:NilClass :(

I want to restrict the access to my pannel admin (gem active_admin) for admin only.
That's my code
class ApplicationController < ActionController::Base
def authenticate_admin!
unless current_user.is_admin?
flash[:error] = "Access denied"
redirect_to root_path
end
end
and the problem is : undefined method `is_admin?' for nil:NilClass
there is a boolean admin (0 false, true 1) in my DB
I've to define my is_admin?, but i try and he is never found. So where do i have to do that ?
Thx for your help
The issue is in your error message. nil doesn't have the method 'is_admin?'. This means that your current user variable isn't being set. You need to redirect users who are not logged-in to a screen where they can do so. Then direct them either through this authenticate_admin! function either first to redirect all user who are admin to the /admin path or simply push all users to your home page allowing them to click an admin link.
It could be that current_user is being set correctly, but this method is being called when there is no logged in user.
You should use this method in conjunction with another filter which requires the user to be logged in, ie which requires current_user to be defined. This is typically called require_user
Eg, in your application controller (so it gets inherited by all controllers)
before_filter :require_user
protected
def require_user
unless current_user
redirect_to "/" and return
end
end
You then make exceptions for the non-logged-in actions, with skip_before_filter.
Now, you can add authenticate_admin! as a before filter in your admin controller: it will only ever by called when require_user has already been passed, so it should be safe.
Add try: <% if current_user.try(:is_admin?) %>
Try simply add before_action :authenticate_user! (if your user called 'user') before :authentificate_admin! method. After this change your app will redirect non-logged users to login form first and only after that will ask your user 'is he admin?'.

Access user properties through a helper method in rails

I wrote this helper method:
class ApplicationController < ActionController::Base
# Prevent CSRF attacks by raising an exception.
# For APIs, you may want to use :null_session instead.
protect_from_forgery with: :exception
private
def current_user
#current_user ||= User.find(session[:user_id]) if session[:user_id]
end
helper_method :current_user
end
To which i should be able, in my mind, to do current_user.role == 'some role' but when I do that it spazzes out saying "undefined method role for nil:NilClass" now does that mean the role column is empty and has nothing it in or that the user object is empty? because I assure you I am logged in, I exist in the database and .... the role field in the database is empty how ever.
Update I should probably state that doing User.role == 'admin' works, as their is a role attribute in the database, or well column. Why can't I do .role on current_user?
Based on this error, you can be certain that current_user is returning the value nil. So the issue isn't the method role. You should note that User.role is a class method on the model User, so it is not calling a method on one particular user. current_user.role on the other hand is an instance method for one particular user, the user that is signed in.
I would put the following right above the method that is throwing the error:
raise session[:user_id].inspect
After confirming the appropriate user_id is in the session cookie using the above method, you could also put the following at the end of your current_user helper method to confirm that a user is actually being returned:
raise #current_user.inspect
What is the logic you are using to create the session[:user_id]? Also, you may want to clear your browser cache or open an Incognito Window (in chrome it is cmd + shift + n) and go back through the sign in process of your app.

Agile Web Development with Rails Chapter 14

I am following the example write in Chapter 14 "Logging In" of the book.
I have my view in "127.0.0.1:3000/login" working well, but if i insert my user and password it returns this error:
NoMethodError in SessionsController#create
undefined method `authenticate' for #< User:0x9f75978>
How to solve it?
create method sessions_controller.rb is:
def create
user = User.find_by_name(params[:name])
if user and user.authenticate(params[:password])
session[:user_id] = user.id
redirect_to admin_url
else
redirect_to login_url, alert: "Invalid user/password combination"
end
end
It's trying to call authenticate on User, this means you probably don't have an authenticate method on user. If you do, make sure it's not private.
The code you give tries to call the authenticate method on an instance of a User object.
Based on you comment re: User.authenticate(name, password) you have an authenticate method only on the User class - and it takes both name and password as parameters.
To call the User class method, you'd instead use the following:
user = User.find_by_name(params[:name])
if user && User.authenticate(params[:name], params[:password])
Alternatively, look for an instance-level method called authenticate which (as #caulfield mentioned above) would look something like:
def authenticate(password)
# does stuff
end
instead of User.authenticate(name,password)

Resources