Rails模型验证has_many关系计数

时间:2012-10-13 05:58:59

标签: ruby-on-rails validation activerecord has-many-through

在我的Rails应用程序中,我有Card和Pack模型,以及它们之间的多对多关系。我想验证一个包中是否正好有3张卡片。该包使用复选框实现与卡相关联。

我的问题:运行验证时,似乎没有关联。验证失败,打印输出为“卡计数为:0”。为什么验证运行时没有关联? (注意:当删除验证时,关联是正确的,因此代码可以工作,而不是验证)

# Pack Model
class Pack < ActiveRecord::Base
  has_many :pack_elements
  has_many :cards, :through => :pack_elements
  validate :validate_number_of_cards

  def validate_number_of_cards
    puts "cards count is: " + cards.count
    errors.add(:cards, "A pack must contain exactly 3 cards.") if (cards.count != 3)
  end
end

其他模型正如您所期望的那样,但没有验证。这是Packs表单,它显示所有卡片,每个卡片旁边都有一个复选框,还有一个提交按钮。我想测试一下这些盒子中有三个被检查了,我希望测试在模型中,而不是在表格中。

# packs/_form.html.erb
<%= form_for(@pack) do |f| %>

<div class="field">
  <% @cards.each do |card| %>
      <%= hidden_field_tag "pack[card_ids][]", nil %>
      <%= check_box_tag "pack[card_ids][]", card.id, @pack.card_ids.include?(card.id), id: dom_id(card) %>
      <%= label_tag dom_id(card), card.description %>
      <hr/>
  <% end %>
</div>

<div class="actions">
  <%= f.submit %>
</div>

2 个答案:

答案 0 :(得分:3)

上面实现的问题是我使用的是 count 方法,它进行数据库查找。在验证通过之前,数据库不会保存,因此永远不会起作用。我将实现更改为:

def validate_number_of_cards
  puts "Count shows there are " + cards.count + " cards."  # always returns zero
  puts "Size shows there are " + cards.size + " cards."
  errors.add(:cards, "A pack must contain exactly 3 cards.") if (cards.size != 3)
end

使用 size 方法,它只是查看内存中的内容。这很好。

答案 1 :(得分:0)

验证在Pack Model中。因此,在保存包模型时会触发验证。

您需要在保存卡片模型时处理此验证。