提问人:pinkfloyd90 提问时间:12/2/2022 最后编辑:pinkfloyd90 更新时间:12/3/2022 访问量:193
当表单对象涉及两个具有相同属性名称的模型时,错误附加到错误的输入字段
Error is attached to wrong input field when a form object involves two models with the same attribute name
问:
我正在处理一个表单对象,该对象涉及使用许多相关模型(例如嵌套属性)更新记录。User
Address
Phone
和 模型都有一个属性,因此我为每个 HTML 输入和表单对象属性命名不同。Address
Phone
number
<%= simple_form_for @user_form, method: :patch do |f| %>
<%= f.input :number %>
<%= f.input :phone %>
<% end %>
控制器:
def edit
@user_form = UserForm.new(@user)
end
def update
@user_form = UserForm.new(@user, update_params)
if @customer_update.save
redirect_to :users_path
else
render :edit
end
end
def update_params
params.require(:user_form).permit(:number, :phone)
end
简化表单对象:
class UserForm
include ActiveModel::Model
include ActiveModel::Validations::Callbacks
attr_accessor :number
:phone
attr_reader :user
validate :validate_children
def initialize(user, update_params = nil)
@user = user
super(update_params)
end
def save
user.assign_attributes(user_params)
return false if invalid?
user.save
end
def user_params
{}.tap do |p|
p[:address_attributes] = {number: number}
p[:phone_attributes] = {number: phone}
end.compact
end
def validate_children
promote_errors(user.associated_model.errors) if associated_model.invalid?
end
def promote_errors(child_errors)
child_errors.each do |attribute, message|
errors.add(attribute, message)
end
end
end
我将验证委托给实际和模型,其中有一个Address
Phone
validates :number, presence: true
因此,如果对任一模型进行验证,则错误将提升到表单对象,并显示在无效的输入字段上。
@user_form.errors.keys
=> [:"phone.number", :number]
@user_form.errors.full_messages
=> ["Number can't be blank"]
问题是,例如,如果在提交表单时将字段留空,因为无效的实际属性是 ,则错误将显示在我的表单的输入字段中,或者换句话说,错误会在字段中呈现,因为表单输入被调用相同()。:phone
Phone
number
:number
Phone
number
Address
number
f.input :number
有没有办法改变它或以不同的方式促进错误,这样就不会发生这种情况?上面的代码显然是愚蠢的,如果需要细节,请告诉我。
答:
0赞
max
12/2/2022
#1
这似乎是很多不必要的复杂性。
你通常在 Rails 中设置它的方式是使用(和 SF 包装器):fields_for
simple_fields_for
<%= form_with(model: @user) do |form| %>
<%= form.fields_for(:phone) do |phone_fields| %>
<pre><%= phone_fields.object.errors.full_messages.inspect %></pre>
<% end %>
<%= form.fields_for(:number) do |number_fields| %>
<pre><%= number_fields.object.errors.full_messages.inspect %></pre>
<% end %>
<% end %>
这些方法生成一个表单生成器,调用获取表单生成器包装的模型实例。这样可以很容易地将错误一起显示或按属性显示并使其正确 - 如果您正在处理一对多或多对多而不是一对一,则尤其如此。object
评论
form_object.errors.full_messages_for(:key)