Nested_form_fields在验证失败时显示现有的has_many嵌套字段

时间:2016-03-24 14:13:07

标签: javascript ruby-on-rails ruby nested-attributes

我正在使用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

它在很大程度上起作用。但是在更新现有联系人团队时存在一个优势。在这里,我正在更新联系人,并显示他们有两个现有的关联团队:

existing teams

用户点击每个团队旁边的X以删除它们,以便它们不再显示在页面上,然后用户点击更新以使这些更改生效:

clicks the x's next to each contact

associated teams marked for deletion and don't show

submits changes

验证正确失败,因为用户试图删除所有关联的团队。它正确显示验证错误消息:

error message

然而,问题是表单不会重新显示现有的关联团队!这些协会尚未删除,因此他们仍应表明:

Not showing existing team associations after validation fails

如何在更新现有联系人后验证失败后显示现有的团队关联?

我尝试删除所有_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,在这种情况下,将不再显示所有验证错误。

提前致谢!

1 个答案:

答案 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