Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

undefined method ‘authenticate' in ruby on rails?

I'm a newbie on Ruby on Rails application, I have already created CRUD but still stacked in Login & Logout functionality.

This is my Sessions_controller:

def new
end

def create
  user = User.find_by(email: params[:session][:email].downcase)
  if user && user.authenticate(params[:session][:passkey])
    # Log the user in and redirect to the user's show page.
  else
    # Create an error message.
  flash[:danger] = 'Invalid email/password combination' # Not quite right!
    render 'new'
  end
end

def destroy
end

This is my view: new.html.erb

<%= form_for(:session, url: login_path) do |f| %>

    <%= f.label :email %>
    <%= f.email_field :email, class: 'form-control' %>

    <%= f.label :passkey%>
    <%= f.password_field :passkey, class: 'form-control' %>

    <%= f.submit "Log in", class: "btn btn-primary" %>
<% end %>

This is my model:

class User< ActiveRecord::Base
  validates :first_name, :presence => true, :length => { :in => 3..20 }
  validates :last_name, :presence => true, :length => { :in => 3..20 }
  validates :email, :presence => true, :uniqueness => true, format: { with: /\A[^@\s]+@([^@.\s]+\.)+[^@.\s]+\z/ }
  validates :passkey, :confirmation => true, :length => {:in => 6..20}
end

When I click Login button then showing this error:

NoMethodError in SessionsController#create undefined method `authenticate' for #User:0x0000000d5c65e0>

How can I fix this error?

I'm using ruby 1.9.7 Rails 4.2.5 & mysql2

That would help me a lot, Please.

like image 997
fool-dev Avatar asked Dec 30 '15 09:12

fool-dev


4 Answers

I'm newbie on ruby on rails application

This answer is going to be out of context, but if you're new, I'd most definitely recommend using Devise over rolling your own authentication.

You can see a very good tutorial on how to use Devise here.

--

In short, Devise handles all the back-end for authentication; it's built on top of warden and gives you pre-rolled sessions & registrations controllers.

I recommend Devise to you because you're new.

Creating your own authentication, whilst relatively simple, takes a lot of experience to understand. It seems from your question that you're following a tutorial or whatever, and don't really appreciate the underlying principles governing the process of authenticating a user.

I may be wrong, but if you implement Devise, get it working, then you're able to make your own afterwards...


If you wanted to use Devise, you would do the following:

#Gemfile
gem 'devise', '~> 3.5', '>= 3.5.3'

$ rails generate devise:install
$ rails generate devise User
$ rake  db:migrate

This will set up the default controllers, routes and warden strategies for Devise; it will add itself to your Model and should allow you to run your server and get the authentication working.

You'll want to use the devise helpers to manage access to the different parts of your application:

#app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
   before_action :authenticate_user! #-> user has to "login" to access app
end

In your views, you can use current_user, user_signed_in? and a bunch of other helpers to provide user-centric functionality:

#app/views/layouts/application.html.erb
<%= render partial "nav" if user_signed_in? %>

This is only my recommendation, it won't help you with your own implementation of your authentication. Of course, I'll delete the answer if inappropriate.


To fix the problem you have right now,

undefined method `authenticate'

This means you don't have an authenticate instance method on your User model. You need the following:

#app/models/user.rb
class User < ActiveRecord::Base
   def authenticate
      # do something
   end
end 

One suspects you're trying to invoke Warden's authenticate! method

I don't have huge experience with Warden; you'll want to ensure you're calling the correct methods for it. Because it's rack middleware, all of the warden helpers are available through env["warden"], so I suspect you'll be using something like:

#app/models/user.rb
class User < ActiveRecord::Base
   def authenticate
     env["warden"].authenticate! ....
   end
end
like image 152
Richard Peck Avatar answered Oct 23 '22 14:10

Richard Peck


Just add

has_secure_password

to your User model. Make sure you add

gem 'bcrypt-ruby'

to your gemfile.

add a field called "password_digest" with string in your User model.

That's it. Rails will handle User authentication for you like a charm and you will be able to use #authenticate method on your Model as well!

Edit: you can check out this project at github - Rails Project @ Github I have implemented authentication using Rails on this. Checkout user.rb, gemfile and user_controller.rb.

like image 37
Prasanna Sundar Avatar answered Oct 23 '22 14:10

Prasanna Sundar


If you use the devise gem then you should not use the has_secure_password method. You should use the valid_password? method.

like image 4
manu Avatar answered Oct 23 '22 13:10

manu


Well it seems your User class is missing a authenticate method. You should implement that.

In case you want to use the built in Rails authentication you should add has_secure_password validations: false to your user model.

Ref: http://api.rubyonrails.org/classes/ActiveModel/SecurePassword/InstanceMethodsOnActivation.html#method-i-authenticate

like image 2
Bert Goethals Avatar answered Oct 23 '22 15:10

Bert Goethals