验证表单中是否存在嵌套属性

时间:2016-03-23 20:02:49

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

我有以下关联:

#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的富联接表中指定)。

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

我该怎么做?

我确实查看了nested attributes文档。我还查看了this articlethis article这些都有点过时了。

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

<%= f.nested_fields_for :contacts_teams do |ff| %>
  <%= ff.remove_nested_fields_link %>
  <%= ff.label :team_id %>
  <%= ff.collection_select(:team_id, Team.all, :id, :name) %>
<% end %>
<br>
<div><%= f.add_nested_fields_link :contacts_teams, "Add Team"%></div>

所以当&#34;添加团队&#34;没有点击,然后没有任何东西通过与团队相关的参数传递,因此没有创建contacts_team记录。但是当&#34;添加团队&#34;单击并选择一个团队并提交表单,这样的内容将通过参数传递:

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

5 个答案:

答案 0 :(得分:3)

在Rails 5中,这可以使用:

完成
validates :contacts_teams, :presence => true

答案 1 :(得分:2)

这会对创建和更新contact进行验证:确保至少有一个关联的contacts_team。目前的边缘情况会导致糟糕的用户体验。 I posted that question here。在大多数情况下,虽然这样做。

#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

答案 2 :(得分:1)

如果你有一个嵌套在用户模型中的Profile模型,并且你想验证嵌套模型,你可以这样写:(你还需要validates_presence_of因为validates_associated不验证如果用户没有任何关联的个人资料,则该个人资料)

class User < ApplicationRecord

  has_one :profile
  accepts_nested_attributes_for :profile
  validates_presence_of :profile
  validates_associated :profile

答案 3 :(得分:0)

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

答案 4 :(得分:0)

型号名称: 1:批准 2:roving_sirs

协会: 1:批准 has_many:approval_sirs,:foreign_key =>'approval_id',:depend =>:destroy accepts_nested_attributes_for:approval_sirs,:allow_destroy => true 2:roving_sirs
纯属_to:approval,:foreign_key =>'approval_id'

在rovings.rb中     ##嵌套表单验证     验证:mandatory_field_of_demand_report_sirs

private

def mandatory_field_of_demand_report_sirs
    self.approval_sirs.each do |approval_sir|
        unless approval_sir.marked_for_destruction?
          errors.add(:base, "Demand Report Field are mandatory in SIRs' Detail") unless approval_sir.demand_report.present?
        end
    end
end