I'm working through Railscast: authentication from scratch in Rails 4, though the tutorial was built for Rails 3. For this reason, some changes have had to be made from the original tutorial instructions.
Tutorial: http://railscasts.com/episodes/250-authentication-from-scratch?autoplay=true
Current running into an error
param is missing or the value is empty: session
Thoughts:
- I've compared the 2 controllers below. My change from the tutorial is moving the params into a session_params method.
- I understand the error is because the hash being posted does not contain a hash like
"session" => { }
. But I don't have a deep enough understanding of Rails to solve.
Recommended controller (rails 3)
def create
user = User.authenticate(params[:email], params[:password])
if user
session[:user_id] = user.id
redirect_to root_url, :notice => "Logged in!"
else
flash.now.alert = "Invalid email or password"
render "new"
end
end
My controller (converted to Rails 4)
def create
user = User.authenticate(session_params)
if user
session[:user_id] = user.id
redirect_to root_url, :notice => "Logged in!"
else
flash.now.alert = "Invalid email or password"
render "new"
end
end
private
def session_params
params.require(:session).permit(:email, :password)
end
Up to this point I've only been using Devise for authentication, so a great thanks in advance if you can share any advice.
UPDATE
As requested, form to post session
<h1>Log in</h1>
<%= form_tag sessions_path do %>
<p>
<%= label_tag :email %> <br/>
<%= text_field_tag :email, params[:email] %>
</p>
<p>
<%= label_tag :password %> <br/>
<%= password_field_tag :password %>
</p>
<p class="button"> <%= submit_tag %> </p>
<% end %>
UPDATE 2
Also adding user.rb model
class User < ActiveRecord::Base
attr_accessor :password
before_save :encrypt_password
validates_confirmation_of :password
validates_presence_of :password, :on => :create
validates_presence_of :email
validates_uniqueness_of :email
def self.authenticate(email, password)
user = find_by_email(email)
if user && user.password_hash == BCrypt::Engine.hash_secret(password, password_salt)
user
end
end
def encrypt_password
if password.present?
self.password_salt = BCrypt::Engine.generate_salt
self.password_hash = BCrypt::Engine.hash_secret(password, password_salt)
end
end
end