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

Scott Taylor scott at railsnewbie.com
Fri Feb 13 11:41:49 EST 2009

On Feb 13, 2009, at 10:52 AM, Nick Hoffman wrote:

> 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?

I must say that I found it a bit surprising when I started using rspec  
with rails (back in 0.8 or something like that).

It's something I figured out after a bit of head scratching, but I  
think it's something my specs are better for in the long run.  If it  
didn't call valid?, I'd probably end up defining a helper method for  
my specs that wrapped that behavior.


More information about the rspec-users mailing list