undefined method 'find_by_email' Error - ruby-on-rails

Okay I have been working on this for about 2 hours and am sure there is a very simple solution but unfortunately as a rails novice I can't seem to find it.
I have set up a basic sign up and login system following Ryan Bates Authetication lesson #270.
I keep however receiving the same error when trying to login.
undefined method `find_by_email' for nil:NilClass
I have my sessions controller set up as follows:
class SessionsController < ApplicationController
def new
end
def create
user = user.find_by_email(params[:email])
if user && user.authenticate(params[:password])
session[:user_id] = user.id
redirect_to root_url, :notice => "Logged in!"
else
flash.now.alert = "Invalid email or password"
render "new"
end
end
def destroy
session[:user_id] = nil
redirect_to root_url, :notice => "Logged Out!"
end
end
But am really unsure how to define find_by_email.
Any advice people can offer me on this really would be much appreciated

user.find_by_email(params[:email])
should be
User.find_by_email(params[:email])

Related

Rails: Notice error

While trying to follow a tutorial, I raised an error when I test the "Sign out" link. I checked the difference with the tutor, but I couldn't figure out why I can't do it my way and why the error occurs on this spot.
My code:
class SessionsController < ApplicationController
def create
if user = User.authenticate(params[:email], params[:password])
session[:user_id] = user.id
redirect_to(session[:intended_url] || user), notice:"Welcome back, #{user.name}"
session[:intended_url] = nil
else
flash.now[:alert] = "Invalid email/password combination! you are a failure"
render :new
end
end
def destroy
session[:user_id] = nil
redirect_to root_url, notice: "You're now signed out!"
end
end
The correction code:
class SessionsController < ApplicationController
def new
end
def create
if user = User.authenticate(params[:email], params[:password])
session[:user_id] = user.id
flash[:notice] = "Welcome back, #{user.name}!"
redirect_to(session[:intended_url] || user)
session[:intended_url] = nil
else
flash.now[:alert] = "Invalid email/password combination!"
render :new
end
end
def destroy
session[:user_id] = nil
redirect_to root_url, notice: "You're now signed out!"
end
end
The error that was raised:
SyntaxError in SessionsController#destroy
C:/Users/xcpro/ve2/2B3/app/controllers/sessions_controller.rb:6:
syntax error, unexpected ',', expecting keyword_end
...ession[:intended_url] || user), notice:"Welcome back, #{user... ...
^
The problem is that method redirect_to take parameters only in parentheses, however notice also should passed in it. Add parentheses around all redirect_to parameters:
redirect_to( (session[:intended_url] || user), notice: "Welcome back, #{user.name}" )
or maybe space after redirect_to would work also:
redirect_to (session[:intended_url] || user), notice: "Welcome back, #{user.name}"

Rails 4 StrongAttributes in RailsCast #274

I am new to Rails. Particularly in dealing with the vagaries between Rails 3 and 4. I have been learning from RailsCast and MHartl's tutorial.
I successfully got the code in RailsCast #274 to work by using the answer in the question linked below:
ActiveModel::ForbiddenAttributesError in PasswordResetsController#update
My concern is that this fix will leave me vulnerable to issues in the future, be it security or otherwise. If there is a "right" way to do this I would like to know. Here is my code block:
class PasswordResetsController < ApplicationController
def create
user = User.find_by_email(params[:email])
user.send_password_reset if user
redirect_to root_url, :notice => "Email sent with password reset instructions."
end
def edit
#user = User.find_by_password_reset_token!(params[:id])
end
def update
#user = User.find_by_password_reset_token!(params[:id])
if #user.password_reset_sent_at < 2.hours.ago
redirect_to new_password_reset_path, :alert => "Password reset has expired."
elsif #user.update_attributes(params.require(:user).permit(:password, :password_confirmation))
redirect_to root_url, :notice => "Password has been reset."
else
render :edit
end
end
end
you need to setup your params first. define a private method inside your class
private
def model_params
params.require(:model).permit(:list :all :your :attributes)
end
then when you do an update, use something like:
#model.update(model_params)
mass assignment is a cool thing in rails, but you need to make sure you are protected
hope that helps

Refactoring sessions_controller in Ruby On Rails

I am learning to refactor my code but I am having trouble refactoring a sessions_controller I have in my application.It is violating the "tell don't ask" principle.I am thinking of extracting some logic to its own class but not sure how that would work.Here is the code from the controller.
class SessionsController < ApplicationController
def create
admin = Admin.find_by(email: params[:sessions][:email])
if admin && admin.authenticate(params[:sessions][:password])
sign_in admin
redirect_to anasayfa_path
flash[:success] = 'Başarılı şekilde giriş yapıldı'
else
redirect_to root_path
flash[:error] = 'Giriş bilgilerinde bir hata var'
end
end
end
How would I refactor this?I thought of extracting
admin && admin.authenticate(params[:sessions][:password])
from this method but would that be the best way?Where would I put the class if I extracted this?
First, you could extract admin lookup, as it may be reused in other actions.
Also, you could standardize your flash keys : notice and alert are two standard keys that #redirect_to understands.
class SessionsController < ApplicationController
before_filter :find_admin
def create
if #admin.authenticate(params[:sessions][:password])
sign_in #admin
redirect_to anasayfa_path, notice: 'Başarılı şekilde giriş yapıldı'
else
redirect_to root_path, alert: 'Giriş bilgilerinde bir hata var'
end
end
private
def find_admin
#admin = Admin.where(email: params[:sessions][:email]).first or redirect_to( root_path, alert: 'not logged in' )
end
end
You have to use #where instead of #find_by to avoid exception if admin is not found.
If you want to keep your current flash keys, you can add in an initializer :
ActionController::Flash.add_flash_types( :success, :error )
Path in #redirect_to from #find_admin and when authentication fail should probably points to log in url.
Try this
class SessionsController < ApplicationController
def create
admin = Admin.find_by(email: params[:sessions][:email])
login_status = false
if admin && admin.authenticate(params[:sessions][:password])
sign_in admin
login_status = true
end
login_status ? redirect_to(anasayfa_path, :flash => {:success => 'Başarılı şekilde giriş yapıldı'}) : redirect_to(root_path, :flash => {:error => 'Giriş bilgilerinde bir hata var'})
end
end

using redirect and if multiple times

My question is actually fairly simple, how do I make a create action which checks if a user is logged in, and if she/he is then redirect to the dashboard instead of rendering the index page where they've got links and stuff to go to and sign up. Also why is the code below not working.
class UsersController < ApplicationController
def new
#user = User.new
end
def create
if current_user.nil?
redirect_to dplace_index_path
if current_user
#user = User.new(params[:user])
if #user.save
auto_login(#user)
redirect_to dplace_index_path
end
end
end
end
end
Your code isn't doing what you expect because the if statements are actually nested (you want elsif with this same structure -- or see my suggested fix below). Here's what your code, when properly formatted, actually looks like:
def create
if current_user.nil?
redirect_to dplace_index_path
if current_user
#user = User.new(params[:user])
if #user.save
auto_login(#user)
redirect_to dplace_index_path
end
end
end
end
Logically, you will never get down into the second if statement, because current_user must be nil to enter the first. Try something like this instead:
def create
if current_user
#user = User.new(params[:user])
if #user.save
auto_login(#user)
redirect_to dplace_index_path
end
else
redirect_to dplace_index_path
end
end
I rearranged the code, but it should logically do what you want now. I put the "happy path" first (the current_user exists), and moved the redirect into the else statement.
General user authentication:
def create
user = User.find_by_email(params[:email])
if user && user.authenticate(params[:password])
session[:user_id] = user.id
redirect_to dashboard_url, :notice => "Logged in!"
else
flash.now.alert = "Invalid email or password"
render "new"
end
end
Try:
def create
if current_user.blank? # .blank? will check both blank and nil
# logic when user is not logged in
redirect_to index_path
else
# logic when user is logged in
redirect_to dashboard_path
end
end
def create
redirect_to dplace_index_path unless current_user
# no need to check current_user again
#user = User.new(params[:user])
if #user.save
auto_login(#user)
redirect_to dplace_index_path
end
end

Authentication Problem - not recognizing 'else' - Ruby on rails

I can't seem to figure out what I am doing wrong here. I have implemented the Super Simple Authentication from Ryan Bates tutorial and while the login portion is functioning correctly, I can't get an error message and redirect to happen correctly for a bad login.
Ryan Bates admits in his comments he left this out but can't seem to implement his recommendation. Basically what is happening is that when someone logs in correctly it works. When a bad password is entered it does the same redirect and flashes 'successfully logged in' thought they are not. The admin links do not show (which is correct and are the links protected by the <% if admin? %>) but I need it to say 'failed login' and redirect to login path. Here is my code:
SessionsController
class SessionsController < ApplicationController
def create
if
session[:password] = params[:password]
flash[:notice] = 'Successfully logged in'
redirect_to posts_path
else
flash[:notice] = "whoops"
redirect_to login_path
end
end
def destroy
reset_session
flash[:notice] = 'Successfully logged out'
redirect_to posts_path
end
end
ApplicationController
class ApplicationController < ActionController::Base
helper_method :admin?
protected
def authorize
unless admin?
flash[:error] = "unauthorized request"
redirect_to posts_path
false
end
end
def admin?
session[:password] == "123456"
end
helper :all # include all helpers, all the time
protect_from_forgery # See ActionController::RequestForgeryProtection for details
#
end
You need to use Ruby's comparison operator == rather than the assignment operator =. Your create action should be:
def create
if session[:password] == params[:password]
flash[:notice] = 'Successfully logged in'
redirect_to posts_path
else
flash[:notice] = "whoops"
redirect_to login_path
end
end
Edit: The problem is that nowhere in your SessionsController are you actually checking the entered password against the correct password. Change your create method to this:
def create
if params[:password] == '123456'
session[:password] = params[:password]
flash[:notice] = 'Successfully logged in'
redirect_to posts_path
else
flash[:notice] = "whoops"
redirect_to login_path
end
end
It's not ideal having the password hard-coded like this and storing it in the session for use by the admin? helper method, but this is supposed to be super simple authentication.
if #YOU MISSING SOMETHING HERE WHICH Returns TRUE IF USER IS VALID
session[:password] = session[:password]
flash[:notice] = 'Successfully logged in'
redirect_to posts_path
else
flash[:notice] = "invalid login" #CHange if messaage for invalid login
redirect_to login_path
end
it must be
if session[:password] == params[:password]
You never have a fail condition due to:
if session[:password] = session[:password]
This will always be true. You probably want something like:
if session[:password] == 'canihazpasswrd' then
do_something_here
Edit: Refer #john's answer. :)
Try this:
def create
if session[:password] == '123456'
flash[:notice] = 'Succesfully logged in'
redirect_to home_path
else
flash[:notice] = "Incorrect Password!"
redirect_to login_path
end
end
The thing is that the tutorial you used does no user's authentication. It only checks if the login belongs to an admin, so some content will be showed.
This way you'll never have wrong login/password, just admin/non-admin.

Resources