Rails - 未知属性密码

时间:2017-04-09 02:16:54

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

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

我认为添加" has_secure_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_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

1 个答案:

答案 0 :(得分:0)

更新:

我已经测试了这个并且它有效。所以希望对你也有用:)看起来MiniTest与BCrypt不兼容。我收到了同样的错误 - 未定义的密码,但后来实现了我的更改,它进展得更顺利。

原始答案:

从你创立的solution开始,它让我觉得这没有任何意义 - 为:password和{添加 getter ,特别是 setter 方法{1}}。因为:password_confirmation创建了那些通过BCrypt运行的虚拟。所以它不是围绕加密/加密吗?如果是这样,那就不安全了。所以只留下测试选项我看到将BYcript带入测试套件。我认为像这样的东西可以做trck:

在用户测试中:

has_secure_password

请注意,我删除了重复的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表单。

P.S。并请修复User类的代码片段。或者它是否真的定义了两次?:

atr_accessor :password, :password_confirmation