简体   繁体   中英

Remember Me authenticity token not working rails

I followed RailsCast 274 to add Remember Me & Reset Password functionality to my app.

I have no problem locally, the app seems to run and authenticate users fine. The problem is when I deploy the production version to Heroku I get the error:

undefined method `find_by_auth_token!' for #<Class:0x007f35fbe37a78>

current_user is defined in my ApplicationController as:

class ApplicationController < ActionController::Base

  protect_from_forgery with: :exception

  helper_method :current_user
  before_action :require_user

  def current_user
    @current_user ||= User.find_by_auth_token!(cookies[:auth_token]) if cookies[:auth_token]
  end

  def require_user
    if current_user.nil?
      redirect_to new_session_path
    end
  end
end

This is my SessionsController :

class SessionsController < ApplicationController
  layout false
  skip_before_action :require_user

  def create
    user = User.find_by(email: params["email"])
    if user && user.authenticate(params["password"])
      if params[:remember_me]
        cookies.permanent[:auth_token] = user.auth_token
      else
        cookies[:auth_token] = user.auth_token
      end

      redirect_to root_path, notice: "Login successful!"
    else
      redirect_to new_session_path, alert: "Email or password incorrect"
    end
  end

  def destroy
    cookies.delete(:auth_token)
    redirect_to new_session_path, notice: "Logout successful!"
  end
end

And this is the User model:

class User < ActiveRecord::Base
  has_secure_password

  has_one :patient, :dependent => :destroy
  has_one :clinician, :dependent => :destroy
  accepts_nested_attributes_for :patient,  :allow_destroy => true 
  accepts_nested_attributes_for :clinician,  :allow_destroy => true

  validates :password,
    :length => { :minimum => 6 }, :if => :password_digest_changed?
  validates_presence_of     :password, on: :create

  before_validation(on: :update) do
    # only want confirmation validation to run if user enters password
    self.password_confirmation = nil unless self.password.present?
  end

  # validates_uniqueness_of :email

  before_create { generate_token(:auth_token) }

  def send_password_reset
    generate_token(:password_reset_token)
    self.password_reset_sent_at = Time.zone.now
    save!
    UserMailer.password_reset(self).deliver
  end

  def generate_token(column)
    begin
      self[column] = SecureRandom.urlsafe_base64
    end while User.exists?(column => self[column])
  end
end

And in my schema.rb :

create_table "users", force: true do |t|
  t.string   "timezone"
  t.boolean  "terms_agreement",        default: false
  t.string   "email"
  t.string   "password_digest"
  t.string   "auth_token"
  t.string   "password_reset_token"
  t.datetime "password_reset_sent_at"
end

Why is this working in development but not production?

Ruby 2.2.1 & Rails 4.1.8

development: PostgresSQL 9.4.1

It's an old tutorial, rails 4 has different dynamic matchers

Rails 3

User.find_by_auth_token!(cookies[:auth_token])

Rails 4

User.find_by!(auth_token: cookies[:auth_token])

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM