You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Ruby on Rails密码文本框输入无法被识别的问题排查

Ruby on Rails密码文本框输入无法识别问题

相关文件配置

1. 数据库迁移文件

  • create_users.rb
class CreateUsers < ActiveRecord::Migration[7.0]
  def change
    create_table :users do |t|
      t.string :name
      t.string :email

      t.timestamps
    end
  end
end
  • add_index_to_users_email.rb
class AddIndexToUsersEmail < ActiveRecord::Migration[7.0]
  def change
    add_index :users, :email, unique: true
  end
end
  • add_password_digest_to_users.rb
class AddPasswordDigestToUsers < ActiveRecord::Migration[7.0]
  def change
    add_column :users, :password_digest, :string
  end
end

2. schema.rb

ActiveRecord::Schema[7.0].define(version: 2023_03_09_015742) do
  enable_extension "plpgsql"

  create_table "microposts", force: :cascade do |t|
    t.text "content"
    t.integer "user_id"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
  end

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

3. 用户注册表单(form.html.erb)

<%= form_with(model: user) do |form| %>
  <% if user.errors.any? %>
    <div style="color: red">
      <h2><%= pluralize(user.errors.count, "error") %> prohibited this user from being saved:</h2>

      <ul>
        <% user.errors.each do |error| %>
          <li><%= error.full_message %></li>
        <% end %>
      </ul>
    </div>
  <% end %>

  <div class="container h-100">
    <div class="row align-items-center h-100">
        <div class="col-6 mx-auto">
            <div class="jumbotron">
                 <form>
                    <div class="form-group">
                        <%= form.label :name, style: "display: block" %>
                        <%= form.text_field :name, class: "form-control" %>
                    </div>
                    <div class="form-group">
                        <%= form.label :email, style: "display: block" %>
                        <%= form.text_field :email, class: "form-control" %>
                    </div>
                    <div class="form-group">
                        <%= form.label :password, style: "display: block" %>
                        <%= form.text_field :password, class: "form-control" %>
                    </div>
                    <br/>
                    <div class="center">
                    <%= form.submit class: 'btn btn-outline-success' %>
                    </div>
                  </form>
            </div>
        </div>
    </div>
</div>

<% end %>

4. Users控制器

class UsersController < ApplicationController
before_action :set_user, only: %i[ show edit update destroy ]

  # GET /users or /users.json
  def index
    @users = User.all
  end

  # GET /users/1 or /users/1.json
  def show
  end

  # GET /users/new
  def new
    @user = User.new
  end

  # GET /users/1/edit
  def edit
  end

  # POST /users or /users.json
  def create
    @user = User.new(user_params)

    respond_to do |format|
      if @user.save
        format.html { redirect_to user_url(@user), notice: "User was successfully created." }
        format.json { render :show, status: :created, location: @user }
      else
        format.html { render :new, status: :unprocessable_entity }
        format.json { render json: @user.errors, status: :unprocessable_entity }
      end
    end
  end

  # PATCH/PUT /users/1 or /users/1.json
  def update
    respond_to do |format|
      if @user.update(user_params)
        format.html { redirect_to user_url(@user), notice: "User was successfully updated." }
        format.json { render :show, status: :ok, location: @user }
      else
        format.html { render :edit, status: :unprocessable_entity }
        format.json { render json: @user.errors, status: :unprocessable_entity }
      end
    end
  end

  # DELETE /users/1 or /users/1.json
  def destroy
    @user.destroy

    respond_to do |format|
      format.html { redirect_to users_url, notice: "User was successfully destroyed." }
      format.json { head :no_content }
    end
  end

  #show micropost for the user
  def show
    @user = User.find(params[:id])
    @micropost = @user.microposts.first
  end

  private
    # Use callbacks to share common setup or constraints between actions.
    def set_user
      @user = User.find(params[:id])
    end

    # Only allow a list of trusted parameters through.
    def user_params
      params.require(:user).permit(:name, :email)
    end
end

问题详情

提交注册表单时,明明输入了sample_password1234这类密码,却始终弹出错误提示:

Password can't be blank
Password is too short (minimum is 6 characters)

控制台沙箱里创建用户操作正常,但一开始控制器的user_params没允许password参数。后来加上password参数后能创建用户了,但查询user.password返回的是nil。


解决方案

1. 修复表单嵌套问题

你的ERB表单里嵌套了两层<form>标签:外层是form_with生成的Rails表单,内层又手写了原生<form>,这会导致表单提交时,密码参数无法被Rails表单助手正确捕获,根本没传到后端。

删掉内层的<form>和</form>标签,同时把密码输入框从text_field改成password_field(标准做法,避免密码明文显示),修改后的表单代码:

<%= form_with(model: user) do |form| %>
  <% if user.errors.any? %>
    <div style="color: red">
      <h2><%= pluralize(user.errors.count, "错误") %> 阻止了用户创建:</h2>

      <ul>
        <% user.errors.each do |error| %>
          <li><%= error.full_message %></li>
        <% end %>
      </ul>
    </div>
  <% end %>

  <div class="container h-100">
    <div class="row align-items-center h-100">
        <div class="col-6 mx-auto">
            <div class="jumbotron">
                    <div class="form-group">
                        <%= form.label :name, style: "display: block" %>
                        <%= form.text_field :name, class: "form-control" %>
                    </div>
                    <div class="form-group">
                        <%= form.label :email, style: "display: block" %>
                        <%= form.text_field :email, class: "form-control" %>
                    </div>
                    <div class="form-group">
                        <%= form.label :password, style: "display: block" %>
                        <%= form.password_field :password, class: "form-control" %>
                    </div>
                    <br/>
                    <div class="center">
                    <%= form.submit class: 'btn btn-outline-success' %>
                    </div>
            </div>
        </div>
    </div>
</div>

<% end %>

2. 更新控制器参数白名单

确保user_params包含password参数,修改后的代码:

def user_params
  params.require(:user).permit(:name, :email, :password)
end

3. 完善User模型配置

你已经添加了password_digest字段,但还需要在app/models/user.rb里启用has_secure_password,Rails才会自动处理密码加密存储,同时提供密码验证逻辑:

class User < ApplicationRecord
  has_secure_password
  # 可选:添加密码长度验证,和错误提示对应
  validates :password, length: { minimum: 6 }
end

4. 关于user.password返回nil的说明

使用has_secure_password后,password是虚拟属性,不会被存储到数据库,数据库里只有加密后的password_digest。所以查询user.password返回nil是正常现象,验证用户登录时用authenticate方法即可:

user = User.find_by(email: params[:email])
if user&.authenticate(params[:password])
  # 登录成功逻辑
else
  # 登录失败逻辑
end

内容的提问来源于stack exchange,提问作者JS3

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 15:09:59