Reputation: 16403
I have a model eclub, which has many invites, and I want to limit the number of invites that can be added. My model looks like this
class Eclub < ActiveRecord::Base
has_many :invites, dependent: :destroy
validates :invites, length: {maximum: 50, message: 'The maximum number of invites have been sent' }
which according to this SO answer should work provided I am not concerned about invites marked for destruction. My rspec test first creates an eclub and successfully adds 50 invites to it. Then
invite = Invite.new(name: 'Too Many', email: '[email protected]')
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
The first two expectations pass, but the last fails with
Failure/Error: expect(eclub.reload.invites.size).to eq 50
expected: 50
got: 51
How do I prevent the extra invite from being added to the collection?
Upvotes: 2
Views: 1219
Reputation: 4920
The best place to add this validation is not in Eclub
but Invite
model. Try this:
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
Also, this code validates :invites, length: {maximum: 50, message: 'The maximum number of invites have been sent' }
won't work because it assumes invites
to be a string.
Upvotes: 4
Reputation: 27747
validates length
is intended to measure the length of a string, and probably doesn't work well with integers.
What you probably want to try is validates :numericality => {:maximum => 50}
EDIT yeah, what I have here probably wont' work either as it's the count of invites (not the invites association itself) that is what we need to validate, so here's a custom validator that should do what you want:
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
Upvotes: -1
Reputation: 223
validates(
:invites,
numericality: {
greater_than_or_equal_to: 0,
less_than_or_equal_to: 50
}
)
Upvotes: -2