我正在创建一个表单,以使用Devise更新我的Rails应用中的用户。
我已经将我的用户数据分为一个用于电子邮件和密码的用户模型,以及一个用于所有其他数据的配置文件表。
创建了一个表单来更新这些详细信息。表单呈现良好,并且正在发送参数,但是当我尝试更新嵌套记录的first_name时出现此错误。
ActiveRecord :: RecordNotSaved已保存在Devise :: RegistrationsController#update
中无法删除现有的关联配置文件。记录的外键设置为nil后,保存失败。
提取的来源(第93行附近):
if target.persisted? && owner.persisted? && !target.save set_owner_attributes(target) raise RecordNotSaved, "Failed to remove the existing associated #{reflection.name}. " "The record failed to save after its foreign key was set to nil." end
模型看起来像
class User < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable
has_one :profile
after_create :create_profile
accepts_nested_attributes_for :profile
end
class Profile < ApplicationRecord
belongs_to :user
end
控制器看起来像
class ApplicationController < ActionController::Base
before_action :configure_permitted_parameters, if: :devise_controller?
protected
def configure_permitted_parameters
devise_parameter_sanitizer.permit(:sign_up) { |u|
u.permit(:email, :password, [profile_attributes: [:id, :first_name, :last_name]])
}
devise_parameter_sanitizer.permit(:account_update) { |u|
u.permit(:email, :password, [profile_attributes: [:id, :first_name, :last_name]])
}
end
end
class UsersController < Devise::RegistrationsController
def create
super
end
def show
@user = current_user
end
def edit
@user = current_user
super
end
def update
@user = current_user
super
end
end
视图看起来像
<h1>Account Details</h1>
<p><strong>Email Address:</strong> <%= @user.email %></p>
<p><strong>First Name:</strong> <%= @user.profile.first_name %></p>
<p><strong>Last Name:</strong> <%= @user.profile.last_name %></p>
<p><strong>Description:</strong> <%= @user.profile.description %></p>
<%= form_for(resource, as: resource_name, url: registration_path(resource_name), html: { method: :put }) do |f| %>
<%= devise_error_messages! %>
<div class="field">
<%= f.label :email %><br />
<%= f.email_field :email, autofocus: true, autocomplete: "email" %>
</div>
<%= f.fields_for :profile_attributes, {html: { method: :put}} do |p| %>
<div class="field">
<%= p.label :first_name %><br />
<%= p.text_field :first_name %>
</div>
<% end %>
<% if devise_mapping.confirmable? && resource.pending_reconfirmation? %>
<div>Currently waiting confirmation for: <%= resource.unconfirmed_email %></div>
<% end %>
<div class="field">
<%= f.label :password %> <i>(leave blank if you don't want to change it)</i><br />
<%= f.password_field :password, autocomplete: "new-password" %>
<% if @minimum_password_length %>
<br />
<em><%= @minimum_password_length %> characters minimum</em>
<% end %>
</div>
<div class="field">
<%= f.label :password_confirmation %><br />
<%= f.password_field :password_confirmation, autocomplete: "new-password" %>
</div>
<div class="field">
<%= f.label :current_password %> <i>(we need your current password to confirm your changes)</i><br />
<%= f.password_field :current_password, autocomplete: "current-password" %>
</div>
<div class="actions">
<%= f.submit "Update" %>
</div>
<% end %>
<br><br>
<%= button_to "Delete Account", registration_path(resource_name), data: { confirm: "Are you sure?" }, method: :delete %></p>
我该如何解决?
答案 0 :(得分:1)
您需要在表单内使用现有用户的个人资料。将fields_for
的行更改为:
<%= f.fields_for resource.profile do |p| %>
请注意,由于它不是单独的表格,因此在这里不需要method