Reputation: 69
I have been unable to wrap my head around how to get these tests back to green.
Model
validates :email, presence: true, format: { with: VALID_EMAIL_REGEX },
uniqueness: true
validates :zip, presence: true, format: { with: VALID_ZIP_REGEX }
validates_numericality_of :puzzle_pieces, only_integer: true
Spec
it { should validate_presence_of(:email) }
it { should validate_uniqueness_of(:email) }
it { should allow_value('[email protected]', '[email protected]').for(:email) }
it { should_not allow_value('john2example.com', 'john@examplecom').for(:email) }
it { should validate_presence_of(:zip) }
it { should allow_value('35124', '35124-1234').for(:zip) }
it { should_not allow_value('5124', '35124-12345').for(:zip) }
it { should validate_numericality_of(:puzzle_pieces).only_integer }
The above tests pass until I add this custom validation.
Custom Validator
class PiecesValidator < ActiveModel::EachValidator
def validate_each(record, attribute, value)
unless value > 0 && value <= Puzzle.remaining
record.errors[attribute] << (options[:message] || "Puzzle pieces must be between 1 and #{Puzzle.remaining}")
end
end
end
Model
validates :puzzle_pieces, pieces: true
Spec
it "does not allow a negative number of puzzle pieces to be saved" do
order = build(:order, puzzle_pieces: -1)
expect(order).to be_invalid
end
That last test passes, but all of my shoulda tests then fail with the same error
NoMethodError:
undefined method `>' for nil:NilClass
I am not understanding how to fix this. It seems that the shoulda tests operate in isolation just fine. But then they all blow up when the custom validation is added in.
Any help pushing me towards understanding this would be greatly appreciated!
Upvotes: 1
Views: 1198
Reputation: 44685
Your problem is that your validation is not expecting value
to be nil. Change your method to:
class PiecesValidator < ActiveModel::EachValidator
def validate_each(record, attribute, value)
unless value && value > 0 && value <= Puzzle.remaining
record.errors[attribute] << (options[:message] || "Puzzle pieces must be between 1 and #{Puzzle.remaining}")
end
end
end
This will not add an error if validated field is blank. However, what you are trying to do can be achieved using standard rails validators:
validates :puzzle_pieces, numericality: { only_integer: true, less_then: Puzzle.remaining, greater_then: 0 }
Upvotes: 3