validation表单中是否存在嵌套属性

我有以下协会:

#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 

contact应始终至少有一个关联的团队(在contacts_teams的富联接表中指定)。

如果用户尝试创建没有关联团队的联系人:应该抛出validation。 如果用户尝试删除所有联系人的关联团队:应该抛出validation。

我怎么做?

我确实查看了嵌套属性文档。 我也看过这篇文章和这篇文章都有点过时了。

完成:我使用nested_form_fields gem动态地向联系人添加新的关联团队。 以下是表单上的相关部分(有效,但目前尚未validation至少有一个团队与该联系人关联):

      

因此,当未单击“添加团队”时,没有任何内容通过与团队相关的参数传递,因此不会创建contacts_team记录。 但是当点击“添加团队”并选择一个团队并提交表单时,这样的事情会通过参数传递:

 "contacts_teams_attributes"=>{"0"=>{"team_id"=>"1"}} 

这会对创建和更新contact进行validation:确保至少有一个关联的contacts_team 。 目前的边缘情况会导致糟糕的用户体验。 我在这里发布了这个问题 。 在大多数情况下,虽然这样做。

 #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 

在Rails 5中,这可以使用:

 validates :contacts_teams, :presence => true 

docs建议使用reject_if并传递一个proc:

 accepts_nested_attributes_for :posts, reject_if: proc { |attributes| attributes['title'].blank? } 

http://api.rubyonrails.org/classes/ActiveRecord/NestedAttributes/ClassMethods.html

如果您有一个嵌套在User模型中的Profile模型,并且您想要validation嵌套模型,您可以编写如下内容:(您还需要validates_presence_of因为如果用户没有任何关联, validates_associated不会validation配置文件轮廓)

 class User < ApplicationRecord has_one :profile accepts_nested_attributes_for :profile validates_presence_of :profile validates_associated :profile