【问题标题】:Rails - Unknown attribute passwordRails - 未知属性密码
【发布时间】:2017-09-04 06:25:37
【问题描述】:

我一直在关注 Michael Hartl 的 Ruby on Rails 教程书,尝试将用户添加到我的应用程序。阅读第 6 章,我添加了我认为对我的用户来说是必要的字段,特别是通过“has_secure_password”进行密码和密码确认。

我认为向我的用户模型添加“has_secure_password”将包括属性“password”和“password_confirmation”,前提是我向模型添加了“password_digest”。我已经按照书上的指示去做了。但是,当我运行测试时,Rails 给了我以下错误:

Error:
UserTest#test_should_be_valid:
ActiveModel::UnknownAttributeError: unknown attribute 'password' for User.
    test/models/user_test.rb:8:in `setup'

我尝试了this 解决方案,但它仍然给了我同样的错误,无法识别属性“password”或“password_confirmation”。我使用“gem install bcrypt”安装了 bcrypt,并在我的 gem 文件中包含了以下内容:

gem 'bcrypt-ruby', :require => 'bcrypt'

我正在使用 Rails 5,似乎“has_secure_password”没有提供我需要的密码属性。谁能看到我错过了什么或做错了什么导致“has_secure_password”无法按预期工作?谢谢

用户模型:

class User < ApplicationRecord

  has_many :activities

  class User < ActiveRecord::Base

    attr_accessor :name, :email, :password, :password_confirmation
    has_secure_password

    validates :first_name, presence: true, length: {minimum: 1}
    validates :last_name, presence: true, length: {minimum: 1}
    validates :email, presence: true, uniqueness: true, length: {minimum: 5}
    validates :username, presence: true, uniqueness: true, length: {minimum: 1}
    validates :password_digest, length: {minimum: 6}
    validates :password, :confirmation => true, length: {minimum: 4}
    validates :password_confirmation, presence: true

    #-----------------------New Stuff ---------------------------------------
    acts_as_authentic do |c|
      c.crypto_provider = Authlogic::CryptoProviders::Sha512
    end
    #------------------------------------------------------------------------

    #---------------Unsure if working--------------
    #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, user.password_salt)
        user
      else
        nil
      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
end

由于我仍在学习 Rails,因此模型上的代码混乱表示歉意。

用户控制器:

class UsersController < ApplicationController
  def new
    @user = User.new
  end

  def create
    @user = User.new(user_params)
    if @user.save
      flash[:success] = 'Account created'
    else
      flash[:notice] ='ERROR: Account was not created'
      redirect_to 'users/new'
    end
  end

  def show
    @user = User.find(params[:id])
  end


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

用户表:

 create_table "users", force: :cascade do |t|
    t.string   "first_name"
    t.string   "last_name"
    t.string   "username"
    t.string   "email"
    t.datetime "created_at",        null: false
    t.datetime "updated_at",        null: false
    t.string   "persistence_token"
    t.string   "password_digest"
    t.index ["email"], name: "index_users_on_email", unique: true, using: :btree
  end

用户测试:

require 'test_helper'

class UserTest < ActiveSupport::TestCase
  # test "the truth" do
  #   assert true
  # end
  def setup
    @user = User.new(first_name: 'test', last_name: 'tester', password: '1234',email: 'test1@mail.com',
                     password: 'foobar', password_confirmation: 'foobar')
  end
  test 'should be valid' do
    assert @user.valid?
  end
end

【问题讨论】:

  • 为什么在 User 类中有一个 User 类?为什么要为 password 和 password_confirmation 声明一个 attr_accessor ?

标签: ruby-on-rails ruby-on-rails-5


【解决方案1】:

更新:

我已经对此进行了测试,并且可以正常工作。所以希望对你也有用:) 看起来 MiniTest 不适用于 BCrypt。我收到了同样的错误 - 未定义的密码,但后来实施了我的更改并且进展顺利。


原答案:

在您创建 solution 时,我认为这没有任何意义 - 为 :password:password_confirmation 添加 getter 尤其是 setter 方法。因为has_secure_password 虚拟地创建了通过 BCrypt 运行的那些。那么它不是围绕加密/加密吗?如果是这样,那是不安全的。因此,我看到只剩下测试选项将 BYcript 带入测试套件。我认为这样的事情可能会起到作用:

在用户测试中:

require 'bcrypt'

  def setup
    @user = User.new(first_name: 'test', last_name: 'tester', password: BCrypt::Password.create("my password") ,email: 'test1@mail.com', password_confirmation: 'my password')
  end
  test 'should be valid' do
    assert @user.valid?
  end

请注意,我删除了重复的 password: 'foobar。由于通过该特定测试,您正在测试是否可以创建用户 ,因此不应传递不同的密码甚至重复的属性...为此进行另一次测试(还有结帐装置,它们非常适合为更复杂的情况创建测试对象以及工厂)。

当然,从您的用户模型中删除atr_accessor :password, :password_confirmation

附言并请修复您的用户类代码 sn-p。还是真的像这样定义了两次?:

class User < ApplicationRecord

  has_many :activities

  class User < ActiveRecord::Base

【讨论】:

  • 感谢您的帮助。这很有效,感谢您对用户的两个定义的建议。我对此仍然有些陌生,所以这可能是我试图解决另一个问题但忘记删除它的解决方案。
猜你喜欢
  • 1970-01-01
  • 2017-10-13
  • 2023-04-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多