ruby 为什么设置password_digest在我的Rails控制台中有效,而不是通过控制器逻辑?

lawou6xi  于 2023-03-08  发布在  Ruby
关注(0)|答案(1)|浏览(99)

我正在从头开始练习一些Rails身份验证(sans Devise gem),但由于某种原因在实现ActiveModel::SecurePassword时遇到了一些问题。如果我进入控制台,我可以创建一个新用户,看到所有的验证都得到了执行,如果我保存了一个新用户(例如user.save),我会看到password_digest设置成功。
但是,如果我通过我的用户注册表***创建一个新用户***,我的password_digest每次都是nil。有人知道为什么吗?我确信我的参数被接收到了,因为我可以在保存之前打印它们并查看它们。
关于上下文,我尝试了以下方法:

  • 添加ActiveModel::SecurePassword到我的用户模型
  • 已启用bcrypt gem并运行bundle install
  • 如果我进入irb,我可以生成一个新的示例,就像这样,并看到password_digest
3.2.1 :137 > new_user = User.new(first_name: "test", last_name: "tester", email: "foo@bar.com", password: "123123123")
 => #<User:0x0000000107c5bf40 id: nil, first_name: "test", last_name: "tester", email: "foo@bar.com", password: nil, created_at: nil, updated_at: nil>
3.2.1 :138 > new_user.save
  TRANSACTION (0.7ms)  BEGIN
  User Exists? (0.8ms)  SELECT 1 AS one FROM "users" WHERE "users"."email" = $1 LIMIT $2  [["email", "foo@bar.com"], ["LIMIT", 1]]
  User Create (0.5ms)  INSERT INTO "users" ("first_name", "last_name", "email", "password", "created_at", "updated_at") VALUES ($1, $2, $3, $4, $5, $6) RETURNING "id"  [["first_name", "test"], ["last_name", "tester"], ["email", "foo@bar.com"], ["password", "[FILTERED]"], ["created_at", "2023-03-07 03:36:07.501992"], ["updated_at", "2023-03-07 03:36:07.501992"]]
  TRANSACTION (1.3ms)  COMMIT
 => true
3.2.1 :139 > new_user.password_digest
 => "$2a$12$aIcAuAdSnJhrLw0bWHTh1OgTTmUioB2ra3h12cFNs/IwnJdyRYJEW"
# NOTE:^ Successfully encrypts the password field via Bcrypt

但是,如果我运行注册表单,所有参数都是正确的,我得到这个字段的nil。下面是从注册表单创建的最新用户的irb打印输出:

3.2.1 :140 > latest_user = User.last
  User Load (1.1ms)  SELECT "users".* FROM "users" ORDER BY "users"."id" DESC LIMIT $1  [["LIMIT", 1]]
 => #<User:0x0000000107d75ca0 id: 27, first_name: "Allday", last_name: "Everyday", email: "allday@everyday.com", password: nil, created_at: Tue, 07 Mar 2023 03:39:13.986217000 UTC +00:00, updated_at: Tue, 07 Mar 2023 03:39:13.986217000 UTC +00:00>
3.2.1 :141 > latest_user.password_digest
 => nil
# NOTE: digest is `nil`!

以下是我当前的用户模型和user_controller.rb逻辑,以供参考:

一米十三分一秒

# == Schema Information
#
# Table name: users
#
#  id              :bigint           not null, primary key
#  email           :string
#  first_name      :string
#  last_name       :string
#  password        :string
#  password_digest :string
#  created_at      :datetime         not null
#  updated_at      :datetime         not null
#
class User < ApplicationRecord
  include ActiveModel::SecurePassword
  has_secure_password
  has_secure_password :recovery_password, validations: false
  
  before_save :downcase_email

  validates :email, format: {with: URI::MailTo::EMAIL_REGEXP}, uniqueness: true, presence: true
  validates :first_name, length: {minimum: 2, maximum: 100}, presence: true
  validates :last_name, length: {minimum: 2, maximum: 100}, presence: true
  validates :password, length: {minimum: 8, maximum: 25}, presence: true

  attr_accessor :password_digest, :recovery_password_digest

  private
  def downcase_email
    self.email = email.downcase
  end
end

这是我的控制器逻辑:

一米十四

class UserController < ApplicationController
  # post '/user/register'
  def create
    user = User.new(user_params)
    begin
      user.save!
      session[:user_id] = user.id
      return render json: {success: true, status: 200}
    rescue => exception
      return render json: {success: false, status: 422, error: exception.message}
    end
  end

  private
  def user_params
    params.require(:user).permit(:first_name, :last_name, :email, :password, :password_confirmation)
  end
end

有人看到我做错了什么吗?或者有什么建议吗?为什么在通过控制器方法逻辑创建用户时password_digest可能为null?非常感谢您的时间--在这个问题上被难倒了!

qco9c6ql

qco9c6ql1#

app/models/user.rb中删除此行

attr_accessor :password_digest, :recovery_password_digest

因为attr_accessor创建的getter和setter方法将覆盖Ruby on Rails为数据库中的列自动创建的方法。

相关问题