设计多态关联:如何修复 "User meta must exist" 错误
Devise Polymorphic Association: How to fix "User meta must exist" error
我正在做一个 Rails 5 项目,我正在使用 Device 创建多个使用多态关系的模型,如下所示:
class DeviseCreateUsers < ActiveRecord::Migration[5.0]
def change
create_table :users do |t|
t.string :meta_type
t.integer :meta_id
## Database authenticatable
t.string :email, null: false, default: ""
t.string :encrypted_password, null: false, default: ""
## Recoverable
t.string :reset_password_token
t.datetime :reset_password_sent_at
## Rememberable
t.datetime :remember_created_at
## Trackable
t.integer :sign_in_count, default: 0, null: false
t.datetime :current_sign_in_at
t.datetime :last_sign_in_at
t.string :current_sign_in_ip
t.string :last_sign_in_ip
## Confirmable
# t.string :confirmation_token
# t.datetime :confirmed_at
# t.datetime :confirmation_sent_at
# t.string :unconfirmed_email # Only if using reconfirmable
## Lockable
# t.integer :failed_attempts, default: 0, null: false # Only if lock strategy is :failed_attempts
# t.string :unlock_token # Only if unlock strategy is :email or :both
# t.datetime :locked_at
t.timestamps null: false
end
add_index :users, :email, unique: true
add_index :users, :reset_password_token, unique: true
add_index :users, :meta_id
add_index :users, :meta_type
# add_index :users, :confirmation_token, unique: true
# add_index :users, :unlock_token, unique: true
end
end
user.rb
class User < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
belongs_to :meta, polymorphic: true
end
我有一个 class 看护人(稍后我会添加看护人特定字段)
class CreateCaregivers < ActiveRecord::Migration[5.0]
def change
create_table :caregivers do |t|
t.timestamps
end
end
end
caregiver.rb
class Caregiver < ApplicationRecord
has_one :user, as: :meta, dependent: :destroy
accepts_nested_attributes_for :user
end
我已经为护理人员搭建了控制器 class。这是文件:
class CaregiversController < ApplicationController
before_action :set_caregiver, only: [:show, :edit, :update, :destroy]
# GET /caregivers
# GET /caregivers.json
def index
@caregivers = Caregiver.all
end
# GET /caregivers/1
# GET /caregivers/1.json
def show
end
# GET /caregivers/new
def new
@caregiver = Caregiver.new
@caregiver.build_user
end
# GET /caregivers/1/edit
def edit
end
# POST /caregivers
# POST /caregivers.json
def create
@caregiver = Caregiver.new(caregiver_params)
respond_to do |format|
if @caregiver.save
format.html { redirect_to @caregiver, notice: 'Caregiver was successfully created.' }
format.json { render :show, status: :created, location: @caregiver }
else
format.html { render :new }
format.json { render json: @caregiver.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /caregivers/1
# PATCH/PUT /caregivers/1.json
def update
respond_to do |format|
if @caregiver.update(caregiver_params)
format.html { redirect_to @caregiver, notice: 'Caregiver was successfully updated.' }
format.json { render :show, status: :ok, location: @caregiver }
else
format.html { render :edit }
format.json { render json: @caregiver.errors, status: :unprocessable_entity }
end
end
end
# DELETE /caregivers/1
# DELETE /caregivers/1.json
def destroy
@caregiver.destroy
respond_to do |format|
format.html { redirect_to caregivers_url, notice: 'Caregiver was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_caregiver
@caregiver = Caregiver.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def caregiver_params
params.require(:caregiver).permit(user_attributes: [ :id, :email, :password, :password_confirmation ])
end
end
这是创建表单
<%= form_for(@caregiver) do |f| %>
<% if @caregiver.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(@caregiver.errors.count, "error") %> prohibited this caregiver from being saved:</h2>
<ul>
<% caregiver.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<%= f.fields_for :user do |u| %>
<div class="col-lg-6">
<%= u.label :email %><br>
<%= u.text_field :email %>
</div>
<div class="col-lg-6">
<%= u.label :password %><br>
<%= u.text_field :password %>
</div>
<div class="col-lg-6">
<%= u.label :password_confirmation %><br>
<%= u.text_field :password_confirmation %>
</div>
<% end %>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
我正在遵循 this 示例。
Github 上的示例运行良好。但是,当我尝试创建新的看护人记录时,出现以下错误:
User meta must exist
我找不到错误是什么。
Rails 5 默认需要 belongs_to
关联。要禁用它,您需要将 optional: true
添加到 belongs_to
belongs_to :meta, polymorphic: true, optional: true
我正在做一个 Rails 5 项目,我正在使用 Device 创建多个使用多态关系的模型,如下所示:
class DeviseCreateUsers < ActiveRecord::Migration[5.0]
def change
create_table :users do |t|
t.string :meta_type
t.integer :meta_id
## Database authenticatable
t.string :email, null: false, default: ""
t.string :encrypted_password, null: false, default: ""
## Recoverable
t.string :reset_password_token
t.datetime :reset_password_sent_at
## Rememberable
t.datetime :remember_created_at
## Trackable
t.integer :sign_in_count, default: 0, null: false
t.datetime :current_sign_in_at
t.datetime :last_sign_in_at
t.string :current_sign_in_ip
t.string :last_sign_in_ip
## Confirmable
# t.string :confirmation_token
# t.datetime :confirmed_at
# t.datetime :confirmation_sent_at
# t.string :unconfirmed_email # Only if using reconfirmable
## Lockable
# t.integer :failed_attempts, default: 0, null: false # Only if lock strategy is :failed_attempts
# t.string :unlock_token # Only if unlock strategy is :email or :both
# t.datetime :locked_at
t.timestamps null: false
end
add_index :users, :email, unique: true
add_index :users, :reset_password_token, unique: true
add_index :users, :meta_id
add_index :users, :meta_type
# add_index :users, :confirmation_token, unique: true
# add_index :users, :unlock_token, unique: true
end
end
user.rb
class User < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
belongs_to :meta, polymorphic: true
end
我有一个 class 看护人(稍后我会添加看护人特定字段)
class CreateCaregivers < ActiveRecord::Migration[5.0]
def change
create_table :caregivers do |t|
t.timestamps
end
end
end
caregiver.rb
class Caregiver < ApplicationRecord
has_one :user, as: :meta, dependent: :destroy
accepts_nested_attributes_for :user
end
我已经为护理人员搭建了控制器 class。这是文件:
class CaregiversController < ApplicationController
before_action :set_caregiver, only: [:show, :edit, :update, :destroy]
# GET /caregivers
# GET /caregivers.json
def index
@caregivers = Caregiver.all
end
# GET /caregivers/1
# GET /caregivers/1.json
def show
end
# GET /caregivers/new
def new
@caregiver = Caregiver.new
@caregiver.build_user
end
# GET /caregivers/1/edit
def edit
end
# POST /caregivers
# POST /caregivers.json
def create
@caregiver = Caregiver.new(caregiver_params)
respond_to do |format|
if @caregiver.save
format.html { redirect_to @caregiver, notice: 'Caregiver was successfully created.' }
format.json { render :show, status: :created, location: @caregiver }
else
format.html { render :new }
format.json { render json: @caregiver.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /caregivers/1
# PATCH/PUT /caregivers/1.json
def update
respond_to do |format|
if @caregiver.update(caregiver_params)
format.html { redirect_to @caregiver, notice: 'Caregiver was successfully updated.' }
format.json { render :show, status: :ok, location: @caregiver }
else
format.html { render :edit }
format.json { render json: @caregiver.errors, status: :unprocessable_entity }
end
end
end
# DELETE /caregivers/1
# DELETE /caregivers/1.json
def destroy
@caregiver.destroy
respond_to do |format|
format.html { redirect_to caregivers_url, notice: 'Caregiver was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_caregiver
@caregiver = Caregiver.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def caregiver_params
params.require(:caregiver).permit(user_attributes: [ :id, :email, :password, :password_confirmation ])
end
end
这是创建表单
<%= form_for(@caregiver) do |f| %>
<% if @caregiver.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(@caregiver.errors.count, "error") %> prohibited this caregiver from being saved:</h2>
<ul>
<% caregiver.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<%= f.fields_for :user do |u| %>
<div class="col-lg-6">
<%= u.label :email %><br>
<%= u.text_field :email %>
</div>
<div class="col-lg-6">
<%= u.label :password %><br>
<%= u.text_field :password %>
</div>
<div class="col-lg-6">
<%= u.label :password_confirmation %><br>
<%= u.text_field :password_confirmation %>
</div>
<% end %>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
我正在遵循 this 示例。
Github 上的示例运行良好。但是,当我尝试创建新的看护人记录时,出现以下错误:
User meta must exist
我找不到错误是什么。
Rails 5 默认需要 belongs_to
关联。要禁用它,您需要将 optional: true
添加到 belongs_to
belongs_to :meta, polymorphic: true, optional: true