Rails:缺少参数或值为空:admin

Rails: param is missing or the value is empty: admin

我正在做一个 Rails 项目,我正在为模型和控制器使用命名空间。也就是说,子模型放在名为 user 的目录中,控制器放在名为 users.

的目录中

为了更清楚起见,我有一个 user 模型,它有子模型 adminstudent 使用 单一 Table 继承 (STI)。这些子模型继承了父模型的所有属性,可以单独定义它们的 validationsmethods 并放置在名为 [=21= 的目录中].

我还有 admins_controllerstudents_controller 分别使用 admin 模型和 student 模型。这些控制器放置在名为 users.

的目录中

这是我的代码;

用户模型:

class User < ApplicationRecord
  has_secure_password
end

管理员模型:

class User::Admin < User
end

学生模型:

class User::Student < User
end

管理员控制器:

class Users::AdminsController < ApplicationController
  before_action :set_admin, only: [:show, :edit, :update, :destroy]

  # GET /admins
  # GET /admins.json
  def index
    @admins = User::Admin.all
  end

  # GET /admins/1
  # GET /admins/1.json
  def show
  end

  # GET /admins/new
  def new
    @admin = User::Admin.new
  end

  # GET /admins/1/edit
  def edit
  end

  # POST /admins
  # POST /admins.json
  def create
    @admin = User::Admin.new(admin_params)

    respond_to do |format|
      if @admin.save
        format.html { redirect_to users_admin_path(@admin), notice: 'Admin was successfully created.' }
        format.json { render :show, status: :created, location: users_admin_path(@admin) }
      else
        format.html { render :new }
        format.json { render json: @admin.errors, status: :unprocessable_entity }
      end
    end
  end

  # PATCH/PUT /admins/1
  # PATCH/PUT /admins/1.json
  def update
    respond_to do |format|
      if @admin.update(admin_params)
        format.html { redirect_to users_admin_path(@admin), notice: 'Admin was successfully updated.' }
        format.json { render :show, status: :ok, location: users_admin_path(@admin) }
      else
        format.html { render :edit }
        format.json { render json: @admin.errors, status: :unprocessable_entity }
      end
    end
  end

  # DELETE /admins/1
  # DELETE /admins/1.json
  def destroy
    @admin.destroy
    respond_to do |format|
      format.html { redirect_to users_admins_url, notice: 'Admin was successfully destroyed.' }
      format.json { head :no_content }
    end
  end

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

    # Only allow a list of trusted parameters through.
    def admin_params
      params.require(:admin).permit(:email, :password, :role)
  end
end

路线:

Rails.application.routes.draw do
  namespace :users do
    resources :admins
    resources :students
  end
end

index.html.erb:

<p id="notice"><%= notice %></p>

<h1>Admins</h1>

<table>
  <thead>
    <tr>
      <th>Email</th>
      <th>Password</th>
      <th>Role</th>
      <th colspan="3"></th>
    </tr>
  </thead>

  <tbody>
    <% @admins.each do |admin| %>
      <tr>
        <td><%= admin.email %></td>
        <td><%= admin.password %></td>
        <td><%= admin.role %></td>
        <td><%= link_to 'Show', users_admin_path(admin) %></td>
        <td><%= link_to 'Edit', edit_users_admin_path(admin) %></td>
        <td><%= link_to 'Destroy', users_admin_path(admin), method: :delete, data: { confirm: 'Are you sure?' } %></td>
      </tr>
    <% end %>
  </tbody>
</table>

<br>

<%= link_to 'New Admin', new_users_admin_path %>

show.html.erb:

<p id="notice"><%= notice %></p>

<p>
  <strong>Email:</strong>
  <%= @admin.email %>
</p>

<p>
  <strong>Password:</strong>
  <%= @admin.password %>
</p>

<p>
  <strong>Role:</strong>
  <%= @admin.role %>
</p>

<%= link_to 'Edit', edit_users_admin_path(@admin) %> |
<%= link_to 'Back', users_admins_path %>

_form.html.erb:

<% if @admin.errors.any? %>
  <div id="error_explanation">
    <h2><%= pluralize(@admin.errors.count, "error") %> prohibited this admin from being saved:</h2>

    <ul>
      <% @admin.errors.full_messages.each do |message| %>
        <li><%= message %></li>
      <% end %>
    </ul>
  </div>
<% end %>

<div class="field">
  <%= form.label :email %>
  <%= form.text_field :email %>
</div>

<div class="field">
  <%= form.label :password %>
  <%= form.text_field :password %>
</div>

<div class="field">
  <%= form.label :role %>
  <%= form.text_field :role %>
</div>

<div class="actions">
  <%= form.submit %>
</div>

new.html.erb:

<h1>New Admin</h1>

<%= form_with(model: @admin, url: users_admins_path, local: true) do |form| %>
  <%= render partial: 'form', admin: @admin, locals: { form: form } %>
<% end %>

<%= link_to 'Back', users_admins_path %>

edit.html.erb:

<h1>Editing Admin</h1>

<%= form_with(model: @admin, url: users_admin_path(@admin), local: true) do |form| %>
  <%= render partial: 'form', admin: @admin, locals: { form: form } %>
<% end %>

<%= link_to 'Show', users_admin_path %> |
<%= link_to 'Back', users_admins_path %>

但是,当我尝试创建新管理员或更新现有管理员时,出现错误:

param is missing or the value is empty: admin

我已经尝试调试问题的原因,但还没有成功。我们将不胜感激任何形式的帮助。

仔细检查我的日志后我终于弄明白了。

我是这样解决的:

我检查了 create 操作的 请求参数 ,我意识到它是这种格式的:

{"authenticity_token"=>"qJWlHz7Z5myTH3dwNIjjSOzRDY7JN+LoovaG+8dMBnGFRWImJKlWp8cgF7kwTqJXIxqU2fGVkqW9nhOAJ8vFIg==",
 "user_admin"=>{"email"=>"promise@gmail.com", "password"=>"[FILTERED]", "role"=>""},
 "commit"=>"Create Admin"}

所以请求参数有一个 user_admin 的散列键,值为 emailpasswordrole,而我传​​递的是 admin 散列键入我的 admins_controller.

我所要做的就是修改 admins_controller:

中的 admins_params 私有方法

由此:

def admin_params
  params.require(:admin).permit(:email, :password, :role)
end

对此:

def admin_params
  params.require(:user_admin).permit(:email, :password, :role)
end

问题就解决了。

如果您遇到此类问题,请始终努力检查您的日志或应用程序跟踪中的请求参数。这将为您提供大量信息,帮助您解决问题。

就这些了。

希望对您有所帮助