Nested_form_fields 在验证失败时显示现有的 has_many 嵌套字段
Nested_form_fields show existing has_many nested fields upon validation failure
我正在使用 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' javascript。所以它记得团队被标记为要删除,因此它不会渲染它们。我不知道如何重置 javascript 除非我执行 redirect
,在这种情况下将不再显示所有验证错误。
提前致谢!
答案在这里。我在 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
我正在使用 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' javascript。所以它记得团队被标记为要删除,因此它不会渲染它们。我不知道如何重置 javascript 除非我执行 redirect
,在这种情况下将不再显示所有验证错误。
提前致谢!
答案在这里。我在 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