ruby-on-rails – Rails:如果数据库中没有密码字段,如何从输入验证密码

我有表格的字段:电子邮件,密码_hash和盐.

用户注册时,我想验证密码和密码确认,但我总是收到错误,说密码输入不能为空.

这是我的模特:

attr_accessor :password

validates :password,:presence     => true,:confirmation => true,:length       => { :within => 6..40 }

我客人我无法验证不是数据库的字段,而是如何对用户输入的密码进行验证?

我在数据库中没有密码字段,因为我知道我得到的密码输入然后我将它存储在db password_hash字段中.

编辑:

这是数据库表:

class CreateStudents < ActiveRecord::Migration
  def change
    create_table :students do |t|
      t.string :first_name
      t.string :last_name
      t.string :email
      t.string :password_hash
      t.string :salt

      t.boolean :activated

      t.timestamps
    end
  end
end

这是注册的观点:

<%= form_for @student,url: {action: 'create'} do |form| %>

  <p style="font-size:smaller; color:red">
  <% @student.errors.messages.each do |att,msg| %>
    <%= msg[0] %><br>
  <% end %>
  <p>
  <%= form.label :first_name %><br>
  <%= form.text_field :first_name %>
  <p>
  <%= form.label :last_name %><br>
  <%= form.text_field :last_name %>
  <p>
  <%= form.label :email %><br>
  <%= form.text_field :email %>
  <p>
  <%= form.label :password %><br>
  <%= form.password_field :password %>
  <p>
  <%= form.label :password_confirmation %><br>
  <%= form.password_field :password_confirmation %>
  <p>
  <%= form.submit %>

<% end %>

这是控制器:

def sing_up
    @student = Student.new
    render 'sing_up'
end

def create
    @student = Student.new
    @student.first_name = params[:student][:first_name]
    @student.last_name = params[:student][:last_name]
    @student.email = params[:student][:email]

    @student.salt = BCrypt::Engine.generate_salt
    @student.password_hash = BCrypt::Engine.hash_secret(params[:student][:password],@student.salt)
    if @student.save
        redirect_to controller: 'singups',action: 'index'
    else
        render 'sing_up'
    end
end

而且,这是模特

class Student < ActiveRecord::Base
  attr_accessor :password
    validates :first_name,:length => { minimum: 3,message: "first_name" }
    validates :last_name,message: "last_name" }
    validates :email,:presence => { message: 'email' },:format => { with: /\A[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]+\z/,message: 'email format' },:uniqueness => { message: 'uniqueness?' }
    validates :password,:confirmation => { message: 'password' },:length => { minimum: 6,message: 'password length' }
end

每次用户输入密码时,首次验证都会失败:confirm => {message:’password’},无论密码是什么.

如果我删除验证:密码部分,一切正常,但用户输入的密码未经验证.

解决方法

您正在验证用户的密码属性,但您从未在第一时间为其分配值.至少,您需要将其添加到控制器代码中:

@student.password = params[:student][:password]
@student.password_confirmation = params[:student][:password_confirmation]

但是,更简洁的方法是使用批量分配 – 摆脱所有@ student.xxx = yyy并将其替换为:

@student = Studen.new(params[:student])

然后,将密码哈希方法移动到模型中,并在每次保存之前自动触发它,如果密码属性存在:

class User < ActiveRecord::Base
  # ...
  before_save :hash_password,:if => proc{ |u| !u.password.blank? }
  # ....

  protected

  def hash_password
    self.salt = BCrypt::Engine.generate_salt
    self.password_hash = BCrypt::Engine.hash_secret(password,salt)
  end
end

这样你就不需要在控制器中做任何事了,但是:

def create
  @student = Student.new(params[:student])
  if @student.save
    redirect_to controller: 'singups',action: 'index'
  else
    render 'sing_up'
  end
end

并在模型中包含所有其他逻辑.

编辑:为了使批量分配与最新版本的Rails 3一起使用,您需要将要分配的属性设置为attr_accessible,如下所示:

class Student < ActiveRecord::Base
  # ...
  attr_accessible :first_name,:last_name,:email,:password # but NOT the hash or salt!!

end

相关文章

validates:conclusion,:presence=>true,:inclusion=>{...
一、redis集群搭建redis3.0以前,提供了Sentinel工具来监控各...
分享一下我老师大神的人工智能教程。零基础!通俗易懂!风趣...
上一篇博文 ruby传参之引用类型 里边定义了一个方法名 mo...
一编程与编程语言 什么是编程语言? 能够被计算机所识别的表...
Ruby类和对象Ruby是一种完美的面向对象编程语言。面向对象编...