has_many关联上的验证错误不会阻止保存

时间:2016-08-16 23:27:51

标签: ruby-on-rails rspec

我有一个模型eclub,它有很多邀请,我想限制可以添加的邀请数量。我的模型看起来像这样

class Eclub < ActiveRecord::Base
    has_many :invites, dependent: :destroy
    validates :invites, length: {maximum: 50, message: 'The maximum number of invites have been sent' }

根据此SO answer应该有效,前提是我并不关心标记为销毁的邀请。我的rspec测试首先创建了一个eclub并成功添加了50个邀请。然后

  invite = Invite.new(name: 'Too Many', email: 'extra@gmail.com')
  eclub.invites << invite
  expect(eclub).to be_invalid
  expect(eclub.errors[:invites].first).to include 'maximum number'
  expect(eclub.reload.invites.size).to eq 50

前两个期望通过,但最后一个失败

Failure/Error: expect(eclub.reload.invites.size).to eq 50

       expected: 50
            got: 51

如何阻止将额外邀请添加到集合中?

3 个答案:

答案 0 :(得分:4)

添加此验证的最佳位置不在Eclub而是Invite模型中。试试这个:

class Invite < ActiveRecord::Base
  belongs_to :eclub
  validate :check_invite_count!, on: :create

  private

  def check_invite_count!
    return if eclub.nil?
    if eclub.invites.count > 50
      errors.add(:base, 'Cannot add more than 50 invites for an Eclub')
    end
  end
end

此外,此代码validates :invites, length: {maximum: 50, message: 'The maximum number of invites have been sent' }无法正常工作,因为它假定invites为字符串。

答案 1 :(得分:-1)

validates length旨在测量字符串的长度,并且可能不适用于整数。

您可能想要尝试的是validates :numericality => {:maximum => 50}

EDIT 是的,我在这里可能不会工作,因为这是我们需要验证的邀请(不是邀请协会本身)的计数,所以这里是一个自定义验证器应该做你想要的:

validate :invite_count_is_ok

private

def invite_count_is_ok
  return unless invites.present?
  errors.add(:base, "You may only have up to 50 invites at a time") unless invites.count <= 50
end

答案 2 :(得分:-2)

validates(
  :invites,
  numericality: {
    greater_than_or_equal_to: 0,
    less_than_or_equal_to: 50
  }
)