我正在使用nested_form_fields gem 。我有以下关联,允许联系人
与多个团队
关联:
#models/contact.rb
class Contact < ActiveRecord::Base
has_many :contacts_teams
has_many :teams, through: :contacts
accepts_nested_attributes_for :contacts_teams, allow_destroy: true
end
#models/contacts_team.rb
class ContactsTeam < ActiveRecord::Base
belongs_to :contact
belongs_to :team
end
#models/team.rb
class Team < ActiveRecord::Base
has_many :contacts_team
has_many :contacts, through: :contacts_teams
end
联系人始终必须至少有一个团队
。我创建了一个自定义验证,当用户创建新的联系人
或更新现有的联系人
时,它会检查这一点。
#custom validation within models/contact.rb
class Contact < ActiveRecord::Base
...
validate :at_least_one_contacts_team
private
def at_least_one_contacts_team
# when creating a new contact: making sure at least one team exists
return errors.add :base, "Must have at least one Team" unless contacts_teams.length > 0
# when updating an existing contact: Making sure that at least one team would exist
return errors.add :base, "Must have at least one Team" if contacts_teams.reject{|contacts_team| contacts_team._destroy == true}.empty?
end
end
它在大多数情况下都有效。但更新现有联系人团队时存在一种边缘情况。在这里,我正在更新联系人,它显示他们有两个现有的关联团队:
用户单击每个团队旁边的 X 来删除它们,以便它们不再显示在页面上,然后用户单击更新以使这些更改生效:
验证正确失败,因为用户尝试删除所有关联的团队。它正确显示验证错误消息:
但是,问题是表单不会重新显示现有的关联团队!这些关联尚未删除,因此它们仍应显示:
更新现有联系人时验证失败后如何显示现有团队关联?
我尝试删除所有 _destroy
标志,希望通过这样做,那些关联的团队能够显示出来。不幸的是它没有达到目的:
# block run when update validation fails
else
params[:contact][:contacts_teams_attributes].each do |k,v|
v.delete_if{|k,v| k == "_destroy" && v == "1"}
end
render :edit
end
我认为该页面正在记住之前运行的nested_form_fields' javascript。因此它会记住团队被标记为要删除,因此不会渲染它们。我不知道如何重置 javascript,除非执行重定向
,在这种情况下,所有验证错误将不再显示。
提前致谢!
最佳答案
这就是答案。我更改了 Contact
模型中自定义验证的名称,以便错误消息有意义:
class Contact < ActiveRecord::Base
accepts_nested_attributes_for :contacts_teams, allow_destroy: true
validate :at_least_one_contacts_team
private
def at_least_one_contacts_team
return errors.add :A_Team, "must be present" unless contacts_teams.length > 0
return errors.add :A_Team, "must be present" if contacts_teams.reject{|contacts_team| contacts_team._destroy == true}.empty?
end
end
然后在 ContactsController
的 update
操作中:
def update
authorize @contact
if @contact.update(contact_params)
redirect_to(some_path), success: 'Updated Successfully.'
else
# This next line is what makes it work as expected for that edge case
@contact.contacts_teams.reload if @contact.errors.keys.include?(:A_Team)
render :edit
end
end
关于javascript - Nested_form_fields 在验证失败时显示现有的 has_many 嵌套字段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36202273/