[rspec-users] Is #valid? automatically called?

Nick Hoffman nick at deadorange.com
Fri Feb 13 10:52:06 EST 2009

On 12/02/2009, at 2:59 PM, David Chelimsky wrote:
> On Feb 12, 2009, at 1:03 PM, Nick Hoffman <nick at deadorange.com> wrote:
>> Does RSpec automatically call #valid? on ActiveRecord models?
>> For instance, when this example is run:
>> it 'should reject a nil value' do
>> @form = TimeShiftForm.new :file => nil
>> puts "@form.errors.count = <<#{@form.errors.count}>>"
>> @form.should have(1).error_on :file
> This matcher, have(1).error_on, does call #valid.
>> puts "@form.errors.count = <<#{@form.errors.count}>>"
>> end
>> This is printed:
>> @form.errors.count = <<0>>
>> @form.errors.count = <<1>>
>> However, I never called @form.valid? , which leads me to believe  
>> that RSpec called it for me.
> In this case, yes, because the matcher needs that.
>> If RSpec does in fact call #valid? automatically, should we refrain  
>> from manually calling #valid?
> The fact that you are asking this shows that we're violating the  
> principle of least surprise. We could make it so it doesn't  
> validate, but that would pit the onus on users to validate  
> explicitly (not to mention the upgrade burden).
> Thoughts?
> David

I think it comes down to how much work you expect to have to do  
yourself, versus how much "magic" you expect will, or would like to,  
happen in the background.

It never crossed my mind that a matcher would call #valid? . My  
impression of matchers was that they simply reported on whether or not  
an object had a specific setting/property. I figured the matcher  
simply checked the AR model object for the specified error, regardless  
of whether or not I'd called #valid? .

Personally, I don't think that matchers should be modifying the  
objects that they check. In my mind, a matcher is like an overseer: it  
reads and reports, but doesn't tinker.

Another reason that I think matchers shouldn't call #valid? is because  
of the inconsistencies doing so can produce between spec examples.  
Examples that use have(X).errors_on won't have an explicit call to  
#valid? , while examples that don't use that matcher, but need #valid?  
to be called, will have an explicit called to #valid? .

That's my perspective on the matter. However, I'm not necessarily  
advocating that the current behaviour change. Others have said that  
they find it logical that #valid? is called for them. Who's to say  
who's right?

More information about the rspec-users mailing list