has_and_belongs_to_many验证

时间:2012-01-09 19:45:08

标签: ruby-on-rails-3 validation activerecord

检查以确保创建新记录包括通过has_and_belongs_to_many创建相关记录的最简单方法是什么?例如,我有:

class Person < ActiveRecord::Base
  has_and_belongs_to_many :groups
end

class Group < ActiveRecord::Base
  has_and_belongs_to_many :people
end

我希望验证能够在创建新Person时触发,以确保它们属于至少一个组。

另外,我如何在控制器中构建它?现在我有:

def create
  @person = current_user.people.new(params[:person])
end

我想让params包含一个组哈希,作为一种嵌套资源。

我查看了Rails文档,但我无法在这个特定情况下找到任何内容。如果有人可以向我解释这个问题或指出我正确的方向,我会非常高兴。谢谢!

1 个答案:

答案 0 :(得分:3)

如果要在创建人员期间为用户提供创建一个或多个组的选项,然后验证是否已创建这些组,请指定。否则,此答案的其余部分将专门用于创建一个Person并验证它是否与至少一个现有组相关联。

如果您正在询问如何验证groups_people连接表中是否存在Person-Group关联,则可以使用奇怪的SQL查询来完成此操作,这是不可取的。只要相信经过良好测试的ActiveRecord可以正常工作。

但是,您可以在保存之前验证Person记录中是否存在一个或多个组。

只要您迁移了名为groups_people的连接表:

# db/migrate/xxxxxxxxxxxxxx_create_groups_people
class CreateGroupsPeople < ActiveRecord::Migration
  def change
    create_table :groups_people, :id => false do |t|
      t.string :group_id,  :null => false
      t.string :person_id, :null => false
    end
  end
end

# $ rake db:migrate

,你的控制器是正确的:

# app/controllers/people_controller.rb
class PeopleController < ApplicationController
  def new
    @groups = Group.all
    @person = Person.new
  end

  def create
    @person= Person.new(params[:person])
    if @person.save
      # render/redirect_to and/or flash stuff
    else
      # render and/or flash stuff
    end
  end
end

,您已将所有现有的组选项作为复选框:

# app/views/people/new.html.erb
<%= form_for @person do |f| %>
  <%= f.label :name %>
  <%= f.text_field :name %>
  # same for other person attributes

  <% @groups.each do |g| %>
    <%= check_box_tag 'person[group_ids][]', g.id, false, :id => g.group_name_attr %>
    <%= label_tag g.group_name_attr %>
  <% end %>

  <%= f.submit 'Create!' %>
<% end %>

,然后您可以在您的个人记录中验证组的存在:

class Person < ActiveRecord::Base
  validates_presence_of :groups

  has_and_belongs_to_many :groups
end

validates_associated helper,但在这种情况下,您不需要将Group.all显示为已选中的选项。

此时不需要accepted_nested_attributes_for。如果您在创建人员时为人员创建了一个组。请再次说明是否属于这种情况。

只需注意:验证包含Group.all作为选项的传入表单,可以选择与该人一起创建一个组,但这很复杂。它将涉及绕过可能存在的Group模型的现有验证(如果有的话)。