我正在使用nested_form_fields gem。我有以下关联,允许contact
与多个teams
建立关联:
#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
联系人始终必须至少有一个team
。我创建了一个自定义验证,用于在用户创建新contact
或正在更新现有contact
时对其进行检查。
#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&#39;之前运行过的javascript。所以它记得团队被标记为被删除,因此它们没有渲染它们。除非我执行redirect
,否则我不知道如何重置javascript,在这种情况下,将不再显示所有验证错误。
提前致谢!
答案 0 :(得分:0)
这是答案。我在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
然后在update
的{{1}}行动中
ContactsController