Rails 3:通过关联项验证是不是存在至少一个有多个

Posted

技术标签:

【中文标题】Rails 3:通过关联项验证是不是存在至少一个有多个【英文标题】:Rails 3: validate presence of at least one has many through association itemRails 3:通过关联项验证是否存在至少一个有多个 【发布时间】:2013-07-22 16:38:56 【问题描述】:

我有两个模型:ProjectProjectDiscipline

class Project < ActiveRecord::Base
  has_many :project_disciplinizations, :dependent => :destroy
  has_many :project_disciplines, through: :project_disciplinizations
  attr_accessible :project_discipline_ids
  attr_accessible :project_disciplines_attributes
  accepts_nested_attributes_for :project_disciplines, :reject_if => proc  |attributes| attributes['name'].blank? 
end

class ProjectDiscipline < ActiveRecord::Base
  attr_accessible :name
  has_many :project_disciplinizations, :dependent => :destroy
  has_many :projects, through: :project_disciplinizations
end

class ProjectDisciplinization < ActiveRecord::Base
  attr_accessible :project_discipline_id, :project_id
  belongs_to :project_discipline
  belongs_to :project
end

在新/编辑Project 表单上,我有一个学科列表和每个学科的复选框,以便用户选择学科:

<div class="control-group">
  <label class="control-label">Check disciplines that apply</label>
  <div class="controls">
    <%= f.collection_check_boxes(:project_discipline_ids, ProjectDiscipline.order('name'), :id, :name, , :class => 'checkbox') |input| input.label(:class => 'checkbox')  input.check_box + input.text  %>
    <p class="help-block">You must choose at least one discipline.</p>
  </div>
</div>

我想添加一个验证以要求至少检查一个学科。我试过了,但我还没有弄清楚。如何添加此验证?

【问题讨论】:

【参考方案1】:

您可以编写自己的验证器

class Project < ActiveRecord::Base

  validate :at_least_one_discipline

  private
  def at_least_one_discipline
    # Check that at least one exists after items have been de-selected
    unless disciplines.detect |d| !d.marked_for_destruction? 
      errors.add(:disciplines, "must have at least one discipline")
    end
  end
end

【讨论】:

你能看看我的回答吗?【参考方案2】:

答案前的附注,根据您的模型结构,我将使用 has_and_belongs_to_many 而不是使用此显式链接模型,因为链接模型似乎没有增加任何价值。

不管怎样,答案都是一样的,那就是使用自定义验证。取决于您是按原样处理事情还是简化为 has_and_belongs_to 许多人,您可能希望验证略有不同。

validate :has_project_disciplines

def has_project_disciplines
  errors.add(:base, 'must add at least one discipline') if self.project_disciplinizations.blank?
end

或使用 has_and_belongs_to_many

validate :has_project_disciplines

def has_project_disciplines
  errors.add(:base, 'must add at least one discipline') if self.project_disciplines.blank?
end

【讨论】:

你能看看我的回答吗? 如果你后来破坏了学科,可能会发生一个项目不再有学科,从而处于无效状态。 .empty? 在这里更合适,空白查询返回数据库中的记录,空则 SELECT 1 AS one FROM project_disciplines ` WHERE AND project_disciplines .id = 1 LIMIT 1`,即效率稍高。【参考方案3】:

我更喜欢更简单的方法:

class Project < ActiveRecord::Base
  validates :disciplines, presence: true
end

此代码与 John Naegle 或 Alex Peachey 的代码完全相同,因为 validates_presence_of 也利用了 blank? 方法。

【讨论】:

是的,但是取决于您的表单的设置方式,可能没有一个很好的报告错误的地方,它将附加到 :disciplines 关联(不存在) .其他方法将错误添加到 :base,这可能更合适。

以上是关于Rails 3:通过关联项验证是不是存在至少一个有多个的主要内容,如果未能解决你的问题,请参考以下文章

Rails 2.3 自定义验证与循环检查存在

Rails validates_presence_of 并验证 has_one 关联模型中的存在

rails 范围检查关联是不是不存在

PL/SQL 关联数组验证索引是不是存在

Rails 在幂等种子文件中查找或创建 - 不通过验证

Rails:has_many 通过关联 - 我做对了吗?