I have a fairly simple model being saved, but am getting RSpec failures that I cannot find the solution to. I am also using the shoulda gem.
CharacterSheet model:
class CharacterSheet < ActiveRecord::Base
validates :character_name, :player_name, :strength, :strength_modifier, presence: true
before_validation :calculate_strength_modifier, on: :create
def calculate_strength_modifier
self.strength_modifier = ((self.strength - 10)/2).floor
end
end
RSpec Example:
RSpec.describe CharacterSheet, type: :model do
let(:character_sheet) { CharacterSheet.new(character_name: "Test Character",
player_name: "Michael",
strength: 18) }
describe "attributes" do
it { expect(character_sheet).to validate_presence_of :character_name }
it { expect(character_sheet).to validate_presence_of :player_name }
it { expect(character_sheet).to validate_presence_of :strength }
it { expect(character_sheet).to validate_presence_of :strength_modifier }
it "saves attributes" do
character_sheet.save!
expect(character_sheet).to be_valid
end
end
end
These are the failures I am getting:
Failures:
1) CharacterSheet attributes should require strength to be set
Failure/Error: it { expect(character_sheet).to validate_presence_of :strength }
NoMethodError:
undefined method `-' for nil:NilClass
2) CharacterSheet attributes should require strength_modifier to be set
Failure/Error: it { expect(character_sheet).to validate_presence_of :strength_modifier }
Expected errors to include "can't be blank" when strength_modifier is set to nil,
got no errors
If I create a record in the rails console manually, it looks correct. Just the tests are failing.
Additionally, if I remove the before_validation
call. The only thing that fails is the "saves attributes" example as expected.
ok, first you have to understand the the validate_presence_of
matcher... sets the value of that attribute to nil... and tests that you get an error.
Think of what that means for your before-validation. You have nothing in strength... then before you get to the validation the before-validation trigger is triggered... and you try to take 10 away from nothing and it explodes.
My bet is that you should put a test in there to make sure that doesn't do silly things. Eg:
def calculate_strength_modifier
self.strength_modifier = ((self.strength - 10)/2).floor if self.strength.present?
end